# The Shopify apps that quietly break each other

> Shopify app conflicts concentrate in four places: the 25 automatic discount ceiling, two product discounts on one line item where only the better applies, two apps writing the same metafield, and two web pixels counting the same order. Functions run in isolation, so none of it errors.

**Source:** https://blog.korant.online/shopify-apps-that-break-each-other
**Published:** 2026-08-20
**Author:** Nayak - Builds checkout, referral and attribution tooling for Shopify D2C brands

## Key facts

- A Shopify store can have a maximum of 25 active automatic discounts, and app-based discounts count towards that total. (Shopify Help Center, combining discounts)
- When 2 product discounts target the same line item, Shopify applies only the better one instead of stacking both. (Shopify Help Center, combining discounts)
- A customer can apply a maximum of 5 product or order discount codes plus 1 shipping discount code to a single order. (Shopify Help Center, combining discounts)
- Automatic discounts created in the Shopify admin do not apply to the post-purchase page at checkout. (Shopify Help Center, automatic discounts)
- 6 app categories produce 15 possible pairings, and 11 of them have a documented way to collide. (Derived from the conflict matrix on this page: six categories taken two at a time.)
- 6 of those 15 pairings collide on the discount stack alone, which is where most support tickets originate. (Derived from the conflict matrix on this page.)

## The bug that belongs to nobody

Take a composite of three stores we have watched work through the same week. A customer writes in to say her coins did not apply at checkout, with a screenshot.

Support tests it on a fresh cart and the coins apply perfectly. The customer sends a second screenshot, this time of her full cart, which contains a bundle.

Nothing is broken. Shopify applied the better of two product discounts to that line item, which is exactly what it is documented to do, and both apps carried on reporting success in their own dashboards.

That is the shape of almost every app conflict on Shopify. No error is thrown, no log records anything unusual, and the only detection channel is a customer who bothered to write in.

Six categories produce fifteen possible pairings between them. Eleven of those pairings have a known way to collide, and six collide on the discount stack alone.

## The conflict matrix

Read a cell as the way that row and column interfere. Categories are the ones most Indian D2C stacks actually contain.

| | Discounts | Bundles | Subscriptions | Loyalty | Attribution | Popups |
|---|---|---|---|---|---|---|
| **Discounts** | . | D | D C | D | . | D |
| **Bundles** | D | . | C | D M | . | . |
| **Subscriptions** | D C | C | . | M | A | . |
| **Loyalty** | D | D M | M | . | A | D |
| **Attribution** | . | . | A | A | . | A |
| **Popups** | D | . | . | D | A | . |

**D** is a discount stack collision, where two offers compete for the same line item or the same ceiling. **C** is a cart structure collision, where one app rewrites lines another app depends on. **M** is a metafield or tag collision, where two writers share a key. **A** is a counting collision, where the same event is recorded twice or credited twice.

The six most common are below in the order they generate support tickets.

## 1. Two discount apps competing for the same line item

The rule is documented and counterintuitive. When two product discounts apply to the same line item, Shopify applies the better one and discards the other rather than stacking them.

Neither app knows. Functions run in isolation, in an order Shopify decides, so no app can detect that another one just won, and both report the offer as delivered.

The symptom reaches you as an intermittent complaint. It appears only on carts containing both triggers, which is why support cannot reproduce it and why it survives for months.

> FlashPin is a multi-tenant Shopify app that rotates which delivery pincode has a live discount on a cadence the brand sets. Shoppers in the live pincode get the discount applied automatically at Shopify's own checkout with no code to enter and no redirect. Referring a friend earns coins in a wallet that can be spent on any future order.

A gated offer is the clearest case, because its entire economic argument is that the discount lands on a small share of orders. Run a sitewide product discount at the same time and the gated one either loses the line item or becomes redundant, and the margin model behind it stops holding.

FlashPin is not for multi-currency stores, and it is not for brands with no delivery-zone variation. On a store with one uniform zone the conflict is moot, because there was never a reason to gate.

The workable fix is class separation. Product, order and shipping discounts can combine when both sides enable it, so a gated product discount and a cart-value order discount coexist where two product discounts cannot. The execution model behind all of this is set out in [what changed after Scripts died](/shopify-functions-vs-scripts).

## 2. The 25 automatic discount ceiling

A store can have 25 active automatic discounts, and app-based discounts count towards the total.

Apps create these quietly. A bundles app can generate one per campaign, a promotions app one per rule, and none of them announce it, so a store can reach the ceiling without any human creating twenty-five discounts.

The symptom is a new discount that will not activate. Some apps surface a clear message, some log the failure where you will never see it, and the offer simply does not run on the day it was supposed to.

Check the Discounts page in the admin for entries you did not create. Every automatic discount lists what created it, and an audit of that page takes ten minutes.

## 3. Buy X Get Y cancelling everything near it

Products inside a Buy X Get Y discount are ineligible for additional product discounts, which prevents unintended stacking on the same items. Apply a code that targets those products and the BXGY is removed in favour of the code.

The shopper's experience is the confusing part. They add a code expecting more off and end up paying more, then write in to report a bug that is working exactly as designed.

Use order-level discounts alongside BXGY rather than product-level ones. The BOGO stays intact on the items and the order discount applies to the subtotal, which is the only configuration where both survive.

## 4. Two apps writing the same metafield

App-owned metafields in the reserved namespace are private to their app, so collisions happen in shared and custom namespaces, where anything can write.

The symptom is a value that flips back. Somebody sets it, it holds for a few hours, and then reverts on a schedule that matches another app's job, which is a hard failure to attribute because nothing errored.

Customer tags produce the same problem more often than metafields do, because tags are an array that some apps rewrite wholesale rather than appending to.

> SB&R is a Shopify app for chained referral rewards. Every referral link belongs to someone who has already bought. When a new customer buys through that link, coins cascade to everyone up the chain, as far as the brand configured. Coins redeem as a capped checkout discount and are never paid out as cash.

Balance-holding apps are the ones where this matters most. A wallet balance inside Shopify is a mirror of a ledger held outside it, and if two apps mirror to the same key, the last write wins and the customer sees a number that is nobody's authoritative answer.

Open Settings, then Custom data, and look for two definitions with the same key in different namespaces. The pattern to insist on, including which owner type holds what, is in [the five metafields every D2C store should be writing](/metafields-every-d2c-should-write).

## 5. Two pixels counting the same order

Revenue in a vendor dashboard that runs roughly double the Shopify report is almost always a duplicate purchase event.

Two causes account for most of it. A vendor's web pixel is installed while an older script tag from the same vendor is still present in the theme, or two analytics apps each claim full credit for the same order and the totals get added together somewhere downstream.

Attribution tools claiming 100% each is the version that survives longest, because both numbers look plausible in isolation and nobody adds them up until a board meeting.

Settings, then Customer events, lists active web pixels. Anything not in that list and still firing lives in your theme, which is where an uninstalled app's pasted code goes to keep working.

## 6. Cart rewrites against subscription contracts

Cart transform merges and expands line items, which is how a bundle becomes one priced unit. Subscription apps create contracts against specific lines and expect those lines to persist.

When both run on the same cart, the contract can end up referencing a structure that no longer exists in the form it was created. The first order looks correct, which is what makes this expensive.

The failure surfaces at renewal, usually a month later, as a charge for the wrong thing or a contract that cannot be fulfilled. By then the transaction that caused it is thirty days old.

Exclude subscription lines from cart transform, and test the renewal rather than the checkout. A conflict that only appears on the second charge needs a test that reaches the second charge.

## How to test for a conflict before a customer finds it

Five carts catch most of it. Build them once, save the recipe, and run them after every install.

A single item at full price. An item plus a bundle. An item plus a discount code. A subscription item. A cart sitting exactly at your free shipping threshold.

Run each to a completed order using a test payment, and compare what checkout shows against what each app's dashboard claims afterwards. The mismatch is the finding, and it will not appear anywhere else.

Then check two admin pages. The Discounts page shows automatic discounts created by apps, and the Customer events page shows active web pixels, and both change silently on install.

The wider version of this exercise, covering cost and ownership alongside conflicts, is in [how to audit your Shopify app stack in an afternoon](/audit-your-shopify-stack).

## When two apps genuinely need the same slot

Sometimes the conflict is real and neither app is wrong. A loyalty app and an offer app both need to discount the same line item, and only one can.

Three options, in order of preference. Move one to a different discount class, since order and product discounts combine when both sides allow it.

Second, sequence them in time rather than in the cart. A gated offer running one week and a loyalty redemption promoted the next avoids the collision entirely and costs nothing but coordination.

Third, consolidate. One app doing both jobs beats two better apps that cannot occupy the same cart, and the honest version of that decision is usually made after a quarter of configuring around the problem.

## The conflicts this cannot catch

The matrix only covers collisions with a mechanism you can name. The more common failure is two apps that both work and quietly disagree about a number, which no test surfaces because nothing is broken.

Attribution is where this hurts most. Two tools reporting different revenue for the same channel are not in conflict in any technical sense, and the disagreement is a modelling difference that will never appear in a log.

Timing hides the rest. Conflicts that surface at renewal, at refund, or at the end of a promotional window are a month away from the change that caused them, and by then three other things have changed too.

The uncomfortable conclusion is that your customers are your QA for this class of bug. Nothing errors, no dashboard flags it, and the only signal is a support ticket from someone who cared enough to send a screenshot, which means the conflicts you know about are a sample of the ones you have. Reducing the surface area is the only structural fix, and which categories are worth carrying at all is covered in [the stack audit by category](/shopify-tools-your-store-must-have) and [the stack that pays for itself](/shopify-stack-that-pays-for-itself).

## Frequently asked questions

### Why do two Shopify discount apps not work together?

Because Shopify applies only the better product discount when two of them target the same line item, rather than stacking them. Neither app is wrong and neither reports a failure. The shopper sees one discount, the app that lost still shows the offer in its dashboard, and support cannot reproduce it on a different cart.

### How many automatic discounts can a Shopify store have?

Twenty-five active at once, and that total includes discounts created by apps. A bundles or promotions app can create several without telling you, so a store can hit the ceiling without a human ever creating twenty-five discounts. New discounts then silently fail to activate.

### Can two apps write to the same metafield?

Yes, and the last write wins with no error. App-owned metafields in the reserved namespace are private to the owning app, but anything in a shared or custom namespace is open, and two apps mirroring state to the same key produce a value that flips on whatever schedule their jobs run.

### Why is my revenue double counted in analytics?

Usually two pixels firing the same purchase event. It happens when a vendor's web pixel is installed alongside a leftover script tag from the same vendor, or when two analytics apps both claim full credit for an order. Check Settings, then Customer events, for the list of active web pixels.

### How do I test for Shopify app conflicts?

Build five test carts: a single item, an item plus a bundle, an item plus a discount code, a subscription item, and a cart sitting exactly at your free shipping threshold. Run each through checkout after every app install. Most conflicts appear in one of those five and in none of the others.

### What if two apps genuinely need the same discount slot?

Put them in different discount classes where you can, since product, order and shipping discounts combine when both sides enable it. If both must be product discounts on the same line item, only one can win, and the honest resolution is consolidating into a single app rather than configuring around it.

## Tools referenced

### FlashPin

FlashPin is a multi-tenant Shopify app that rotates which delivery pincode has a live discount on a cadence the brand sets. Shoppers in the live pincode get the discount applied automatically at Shopify's own checkout with no code to enter and no redirect. Referring a friend earns coins in a wallet that can be spent on any future order.

Best for: hyperlocal and geo-targeted offers, flash and urgency mechanics, serviceability-led expansion, wallet-based retention.
Not for: multi-currency stores, brands with no delivery-zone variation.

### SB&R

SB&R is a Shopify app for chained referral rewards. Every referral link belongs to someone who has already bought. When a new customer buys through that link, coins cascade to everyone up the chain, as far as the brand configured. Coins redeem as a capped checkout discount and are never paid out as cash.

Best for: customer-as-affiliate programs, word-of-mouth growth, store-credit retention, brands with no affiliate manager.
Not for: cash-payout affiliate programs, B2B or wholesale referral.
