Release 112
Highlights
Omnichannel commerce: Use the new Limio Partner Portal, integrated with the Limio Catalog, to explore new commerce channels
Flexible pricing and packaging: Volume pricing, Evergreen subscriptions
Improve retention: New Update Subscription capabilities for complex subscription upgrades, downgrades, and add-on management
Breaking Changes
Please note there are several breaking changes in this release. Please read the Stability and Quality Improvements section below to review in detail.
New features and improvements
Introducing the Limio Partner Portal
The new Limio Partner Portal lets you create partner-only pricing pages and checkouts, so partners can purchase subscriptions on behalf of customers without exposing partner pricing to end users.
After a purchase, partners can also manage customer subscriptions using our out-of-the-box subscription management capabilities, such as upgrades, downgrades, add-ons, and cancellations.
Partner capabilities are also available via API, allowing trusted third parties to submit partner orders programmatically.

To support the Partner Portal, we have developed these new out-of-the-box Limio components:
Learn more: https://docs.limio.com/product/partner-portal/partner-portal-overview
Upgrades, downgrades, and add-on management with Update Subscription
With our new Update Subscription capabilities, customers can upgrade, downgrade, or manage add-ons for an existing subscription.
Unlike the existing Switch experience, Update Subscription is designed for multi-product businesses and supports proration visibility, multi-product changes, hybrid pricing, and add-on purchases within the same flow.
Release 112 also adds platform event support for Update Subscription, making subscription changes easier to integrate with Salesforce.
Supported scenarios:
Upgrade a subscription (effective immediately)
Downgrade a subscription (scheduled for end of term)
Add add-ons without changing the base offer
Change the base offer and add-ons in a single flow
Automatically remove incompatible add-ons during upgrades or downgrades

To support Update Subscription, we have developed these new out-of-the-box Limio components:
Note: The Billing Schedule component can no longer be used in Acquisition use cases. It has been reworked to be in Update Subscription use cases only, so please remove it from Acquisition pages.
Volume pricing now supported
Limio now supports volume pricing for offers and add-ons, allowing you to model unit-based charging directly in Limio. This is well suited to B2B and SaaS use cases such as seat-based pricing, data usage, or API call bundles, and enables tiered pricing without adding complexity to the customer journey.
Volume-priced offers and add-ons are supported across acquisition and Update Subscription flows, including initial purchases, add-on purchases, and upgrades or downgrades.
Limio’s out-of-the-box components have also been updated to support quantity selection and tier handling for a consistent checkout and update experience.

Improved out-of-the-box styling in the Modular Checkout
Modular Checkout now has improved styling out-of-the-box to reduce reliance on developer-led styling and to better align with our cart components. This helps non-technical teams ship checkout changes faster, while keeping the experience consistent across journeys.
We've also updated the payment method selector to use a more modern tile interface.

Note: Due to the redesign, we recommend testing your checkout for styling issues, especially the payment method selector, and we also recommend testing styling of any popovers you use through your Limio pages.
Write custom events to the LFS Timeline
A new API lets you write external events into the Limio for Salesforce timeline, so customer service representatives can see a more complete customer history including events that happen outside Limio.
Previously, the timeline only displayed Limio-initiated events sourced from the Limio database. With this API, trusted external systems (such as Zuora, CRM, or partner platforms) can write events to the same event store.
Learn more: https://docs.limio.com/integrations/setting-up-limio-for-salesforce/subscriber-timeline/activity-timeline
Use delivery address for tax calculation when available
The tax preview logic in the Cart Summary component has been updated. When a delivery address is provided, tax is calculated using the delivery address. Otherwise, the billing address is used.
Learn more: https://docs.limio.com/components/component-library/cart-components/component-cart-summary
New journey condition based on subscription billing country
A new condition type, Subscription Billing Country, is now available in Limio Journeys. This allows you to show different Pages to customers based on the billing country of their subscription, rather than their detected IP location.
Support evergreen subscriptions from initial term
You can now configure your offers to be Evergreen from initial term, instead of only in the renewal term as it was previously. Setting the Initial Term offer attribute to Evergreen creates the subscription as evergreen in Zuora immediately on purchase, rather than requiring a renew-to-evergreen transition. All self-service and partner flows (upgrade, downgrade, add-on, cancellation) handle evergreen subscriptions correctly.
Improvements to Salesforce integration
Our Salesforce integration can now be used even when you are not using Limio for Salesforce.
New orders purchased using anonymous authentication include the owner in the platform event.
Bug fixes
Cross-sells not removed in cascade removal scenario
We fixed an issue where cross-sell items were not removed when the base offer was removed, even when the cascade removal prop was enabled.
Billing Schedule component styling issues
We fixed a UI issue where the Billing Schedule background container could appear clipped, improving layout consistency across screen sizes.
Intermittent user creation issue
We fixed intermittent failures where creating a new Limio Commerce user did not consistently create the user or send the expected email.
Subscription owner not displayed when purchased anonymously
We fixed an issue where the subscription owner was not displayed in the Subscriptions Tab view when the subscription was originally purchased with anonymous authentication. Now, the subscription owner is always visible in the Subscription Tab views.
Cart Items prices not aligned in read-only mode
We fixed a display issue where cross-sell add-on pricing could appear misaligned compared to other prices when Cart Items was shown in read-only mode (for example on order complete pages).
Duplicating offers and pages error (#111231, #110848)
We fixed an issue with duplicating offers or pages after selecting a specific offer or page. Now, users can duplicate a specific offer or page, or choose to duplicate offers or pages from the offers or pages tables.
Promo codes applied to rate plan charges that are discount model
We have added a new check to our promo codes to prevent them from being applied to rate plan charges which are a discount model, which is not supported by Zuora.
Stability and quality improvements
Flattened Add-on Order Items
Add-ons are now top-level items in the order, rather than being nested inside their parent offer's orderItem.addOns[] array. This aligns with industry standards and simplifies how add-ons are processed throughout the system.
Add-ons now appear as separate
OrderItems at the same level as main offers, withtype: "add_on"and aparentIdlinking them to their parentMain offers have
type: "offer"The
addOnproperty on order items has been renamed tooffer— add-ons share the same structure as regular offers
Two helper functions are available to filter the order items array:
isOfferOrderItem(item)— true for main offersisAddOnOrderItem(item)— true for add-ons
This improvement has potentially breaking changes:
orderItem.addOns[]no longer exists, so custom components reading nested add-ons from an order item should now read add-ons from the top-level order items array. Use filtering bytype === "add_on"and matching onparentIdorderItem.addOnhas been renamed toorderItem.offer, so custom components or integrations referencingorderItem.addOnshould now referenceorderItem.offer
Backward compatibility for legacy nested structures is preserved during normalisation — existing process events (e.g. credit memo events) using the old format will continue to be handled correctly.
Country logic more consistent
The payment gateway displayed to the customer is now selected based on the customer's billing address country rather than a browser cookie or the offer's allowed countries list.
Address objects (billing and delivery) no longer include a
stateCodefield. For US and Canadian addresses, thestatefield already contains the full state/province name (e.g. "New Jersey", "Ontario") — the abbreviated code (e.g. "NJ", "ON") is no longer returned as a separate field.The way
order.countryis set during the checkout lifecycle has been clarified and made more predictable:At checkout initiation:
order.countryis only set if it is explicitly provided in the request payload. For renewal checkouts, it is taken from the existing subscription's purchase country. The API no longer requires acountryfield to be sent.When fetching a basket: If
order.countryis not already set, the system will now automatically populate it based on the customer's detected location (from CDN/browser headers or thelimio-countrycookie).Billing address updates no longer automatically change
order.country— the two are now independent.
Note: This has 2 potentially breaking changes:
The stateCode on address objects no longer exists. Use the state field instead.
Systems should send data in order.country instead of a top-level country.
Tracking data inside order object
Checkout tracking information (UTM parameters, offer paths, campaign tags, referrer) was previously stored as a separate top-level field alongside the order in the checkout session. It is now stored inside the order as order.tracking.
Note: This has a breaking change for any component or integration reading basketSession.tracking or checkout.tracking. Any components or integrations should read from basketSession.order.tracking instead, though backwards compatibility is ensured in this release.
Basket ID stored in landing-state cookie
The basket (checkout) ID is now managed server-side and stored in the lmo_ls landing-state cookie, replacing the previous approach of storing it in sessionStorage or passing it via URL parameters.
This makes the basket more reliably available across page navigations, browser history traversal, and shared-computer scenarios. Checkout redirect URLs now always include a ?basket=<id> parameter, making the active basket explicitly visible in navigation and access logs.
As part of this change, several top-level fields in the basket response have been deprecated and consolidated under order.*:
basketSession.basket
basketSession.order
basketSession.country
basketSession.order.country
basketSession.locale
basketSession.order.locale
basketSession.tracking
basketSession.order.tracking
basketSession.redirectUrl
Removed — see Basket SDK section below
The basket response no longer includes private server context — only the data relevant to the frontend is returned.
getCheckoutId()has been replaced bygetCurrentBasketId(), which reads from Redux (backed by the cookie) rather thansessionStorageThe
limio_ordersessionStoragekey is no longer written to
This improvement has potentially breaking changes:
If your custom components use any of the deprecated fields, replace them with the new fields.
getCheckoutId()has been removed, so custom components calling it should now usegetCurrentBasketId()sessionStorage["limio_order"]is no longer written to, so custom components reading the basket ID fromsessionStorageshould now usegetCurrentBasketId()from the SDK, or read from thelmo_lscookielmo_lscookie may be missingdomainattribute ifoauth.cookie_domain_mappingis not explicitly configured, so explicitly configureoauth.cookie_domain_mappingif the cookie needs to be set on a parent domain
Basket SDK improvements
In
useBasket():addOfferToBaskethas been removed — useaddToBasketinsteadaddAddOnToBaskethas been removed — useaddToBasketwithparentIdinsteadsyncBaskethas been removed— no longer needed; every basket action now automatically syncs to the server
In
addToBasket():The
pushToCheckout: trueoption no longer clears the basket before adding a new item. The campaign attributepush_to_checkout__limiono longer affects basket behaviour either. UseclearOrderItemsexplicitly if this is needed.redirectUrlis no longer accepted as an option inaddToBasketredirectUrlis no longer read from the?redirect_url=URL query parameterredirectUrlis no longer stored in or returned from basket/checkout session responsesreinitialiseOrderItemsoption also removed fromaddToBasketGoogle Pay's fallback button no longer accepts a
redirectUrlpropredirectStateis unaffected and remains in place
updateBasketDetailsis now included in the SDK. This function is useful to update basket metadata such as billing address, customer details, or custom fields, so the information is available on abandoned baskets
Note: This has a breaking change for any custom components using these affected functions. Please review your custom components, and update them where applicable.
Checkout API Restructuring
The acquisition checkout APIs have been reorganised to follow consistent REST semantics with explicit GET / POST / PUT endpoints.
Create new basket
POST /api/checkout/subscription
Update existing basket
PUT /api/checkout/subscription
Get existing basket
GET /api/checkout/subscription
The public API function initiateCheckoutWithOffer has also been renamed to initiateCheckout.
Note: This has potentially breaking changes:
initiateCheckoutWithOfferwas renamed toinitiateCheckoutand the payload changed, so any integrations callinginitiateCheckoutWithOfferdirectly should now useinitiateCheckout
Removed trialist concept
Limio no longer automatically checks whether a customer has previously used a trial offer and blocks them from accessing another. Specifically:
The backend no longer checks the
trialistflag on customer records at checkoutThe
limio-invalidcookie is no longer set when a customer attempts to take a second trialOffer components (Offers, Grouped Offers) no longer filter out trial offers based on the
limio-invalidcookieThe "ineligible heading" and "ineligible message" props on the Grouped Offers component no longer display a trial warning
Note: This has a breaking change for any customers relying on the trial eligibility check. Use alternative methods like journeys or custom components moving forward.
Improvement to Zuora Order Processing
The Zuora subscription creation pipeline has been refactored to use OrderItem as the single source of truth across all flows — replacing separate code paths for preview orders and new orders. Each order item now creates its own subscription entry with its own start date and subscription reference.
Unified currency formatting
Previously, each component was responsible for reading the locale itself to format currency, which caused inconsistencies across the shop. We now have a unified function for reading the locale that all Limio components use.
Last updated
Was this helpful?

