So, because you are already dealing with "product" data, a simple Merchandising eVar using product syntax and the expiry you need (Visit? 1 Week? etc.... how long do items normally sit in your cart prior to the order being made?).
Interesting fact about s.products, is that the value set in a Merchandising eVar is maintained per product...
So if you have
Product 1 / Merch eVar = "something"
and then
Product 2 / Merch eVar = "other value"
When you purchase both products (and don't pass a merch eVar with them), Product 1 will still stitch to the last value seen on it ("something") and Product 2 will still have "other value". The last touch per product is maintained, it's not the raw last value passed to that eVar; this is another powerful feature of Merchandising eVars.
Now, trying to maintain the full "upgrade path" of the product ([initialProductId]_to_[updatedProductId_1]_to_[updatedProductId_2])
That is going to be a challenge... the value of the eVar is maintained on the server... so it's not like you can append a new value to the existing value.
I don't know if this is going to be feasible... you could try and store the value in a cookie, session or local storage value... but if those are lost (deleted, destroyed between sessions, or the user changes devices, etc) then you won't have the information.
What about just tracking the "X to Y" upgrade on the upgrade (or even if it's always 1 > 2 > 3 > 4, as in they can't super upgrade from 1 > 4, just track the upgrade and not the original value... or track the "original" in one eVar and the upgrade in another?) , and looking at a custom attribution of Participation to see what upgrades the users interacted with on the path to subscription?