Currently, the only mechanism for an app or theme to forward dynamic data about a session into a Function is via Cart Attributes. (cart.attribute: https://shopify.dev/api/functions/reference/order-discounts/graphql/common-objects/cart)
This is an extremely problematic single point of failure, as cart attributes are completely obliterated by Dynamic Checkout (Buy It Now) buttons, meaning Functions relying on attribute data to calculate Discount logic cannot be expected to run reliably on any merchant store including Dynamic Checkout buttons (which are enabled by default in Dawn). This effectively cripples the feature before it's even launched, as traditional workarounds for the Dynamic Checkout button problem (notably, post-Order reconciliation via Webhook and/or Order Status page ScriptTag) are not applicable to Functions.
See the official Help docs on Dynamic Checkout Buttons that note this incompatibility, as well as the myriad community forum issues complaining of this behavior, a handful of which I've linked below:
Thanks for the report! As a workaround or replacement for cart attributes, would line item attributes fit your use case? These are passed with Dynamic Checkout.
Does CartLine.attribute map to line_item.properties?
(And if so, should that be noted / potentially renamed for consistency within the Function docs?)
If so -- that might be a workaround for some cases, but given that there's no clean, reliable way to listen for 'on add to cart' events within themes or theme app extensions, (outside of severe hackery involving maintaining an open socket connection to a backend processing cart/update webhook events, or theme-specific manual code modification involving wrapping / replacing add-to-cart functionality) I don't think it completely solves the problem, since apps don't necessarily have a line item to push data to.
I suppose you could conceive of a workaround polling the cart AJAX API at given intervals to see if it has line items in order to push properties onto them...but at that point we're in 'workarounds on workarounds' territory, still sacrificing reliability, and using a field for something it's not at all intended for.
EDIT: Actually, even then, there's never a guaranteed point at which app code even has a line item in a cart to push data to, since if the first existence of the line item is via dynamic checkout, the app may never GET an opportunity to push data.
We are having a similar problem with line item attributes. We have custom features when added to the cart that are passed with an attribute so we know what customization the customer wants. They work fine as they show in the cart and on the checkout page. However, we have had some orders come through where the attribute isn't showing. What's odd is the same order will have some products showing the attribute and others not. Additionally, we can't recreate the error even using the same products in our test order.
Any thoughts on this issue?
I was trying to figure out why the attributes I was adding via AJAX (as specified here) It wasn't until i stumbled upon this thread that i realized it was the buy now button. This is super painful for me and seems like a big ol bug that should be addressed, as in any attribute added should persist all the way through to the order.
@bishpls were you able to come up with a work around in the mean time?
@Nick_Wesselman Is there an alternative to adding persisted data to the cart/order when a customer checks out using buy now?
A workaround for Functions? Not that I'm aware of*.
A workaround for a more standard checkout / order flow capturing data? Yes, but it's not pretty. Store any attributes you absolutely must have in localStorage or a cookie, run a separate reconciliation script delivered via Order Status Page-scoped ScriptTag, and deal with merging the data into the resulting Order / your database as you see fit.
(* Technically, if disabling the dynamic checkout / Buy It Now button isn't an option, you could theoretically roll your own Buy It Now button and include the cart attributes in the query string of it; under the hood, dynamic checkout buttons basically just use cart permalinks, which allow for the submission of cart attributes to the created Checkout instance automatically as part of the URL. This is ABSOLUTELY something Shopify could resolve on their end, it would just entail a significant change to the default dynamic checkout buttons. I've lodged a few complaints about this issue already and I have a submission somewhere in the archive of the developer Discord pointing out exactly what code that could be changed to accomplish this.)