Problem
How do cart line item keys work in Shopify?
When Shopify applies a discount to an item in the cart, it also changes the "key" of that cart line item. The key of a line item is a unique identifier that consists of the variant id, followed by a colon, followed by a hashcode that changes when:
line item properties change
the selected selling plan (subscription) changes
discounts are applied
The line item key changes when discounts are applied in one of the following ways:
run an automatic discount
use Shopify Plus scripts
use native discount functions
Discount Ninja, when configured to use the Shopify functions checkout mode, leverages native discount functions.
The sequence that causes the issue
Some themes do not handle line item keys properly, a problem that only becomes apparent when discounts are applied after the page has loaded:
the cart page is rendered
the cart line item keys are included in the HTML rendered by Shopify
an interaction (for example a change of quantity) triggers a discount
Shopify changes the key in the backend
the theme does not update the key in the HTML rendered
Some themes rely on the cart line item present in the HTML to perform updates of the cart. For example, when the cart quantity is changed or a line is removed, the theme calls Shopify's Cart.js endpoints using the cart line item key as the unique identifier for the cart line item to update. When the keys are out of synch, this causes those update calls to fail.
So, is this an issue in Discount Ninja?
No, it's a limitation that is inherent to how the Shopify platform works and how themes are built.
To demonstrate this (and test if your theme handles this correctly), run the following test:
Make a copy of your theme
Disable Discount Ninja's App embed on the copy of that theme (cf. https://support.discountninja.io/en/articles/8403197-how-to-enable-or-disable-app-embeds)
Set up an Automatic discount in Shopify's discount module:
Product discount
10 percent
Specific product (select the product you'll use for your test here)
Minimum quantity of items: 99 (make sure this number is high enough not to impact live customers)
Activate this discount.
Preview the copy of your theme.
Ensure the cart is empty.
Next, add 98 items of the selected product to the cart.
Inspect the HTML generated in the cart page. Note the cart line item key. At this point, this key is correct.Then, without refreshing the page, change the quantity of the line from 98 to 99.
The network request to change the quantity will succeed.
The automatic discount will now be applied to the cart and, crucially, Shopify will change the cart line item key. This can be observed in the network requests tab of your browser by inspecting the payload of the request and the response received.Finally, try to change the quantity of the line from 99 to 100.
If this fails with HTTP status code 400, your theme has failed to update the key of the cart line item. The theme has sent a request to Shopify that uses the old key (which no longer exists) as the unique identifier for the line.
Solution
Discount Ninja addresses this shortcoming in the Shopify platform by keeping track of situations where the key of a cart line item changes. This helps the app to avoid many situations where adding a discount would break your theme's ability to update the quantity of the cart.
However, there are situations where your theme's JavaScript may still fail when keys are updated by Shopify. If your theme is in that case, we suggest the following approach:
Work with the theme developer to have this fixed: theme developers may be able to avoid this issue by relying on the line number instead of the key (cf. https://shopify.dev/docs/api/ajax/reference/cart#post-locale-cart-change-js)
Alternatively, programmatically ensure the cart line item keys are updated by leveraging our client-side JavaScript API, documented at https://developers.discountninja.io/.
Our client-side JavaScript API is included in the App embed and can help you implement the second approach. Specifically:
If your theme needs to know when the cart is updated, you can subscribe to this event: https://developers.discountninja.io/discount-ninja-developer-hub/storefront-api/price-rule-engine/javascript-api/events#cart-updated
If you need to update the original keys with the new keys, you can use Discount Ninja's built-in mechanism which tracks the updated cart line item keys: cf. https://developers.discountninja.io/discount-ninja-developer-hub/storefront-api/price-rule-engine/javascript-api/functions#line-item