Home
Wiki
Home
Wiki
  1. 3. Reusables
  • Back to home
  • 1. Themes
  • Vs Code
    • Getting Started
  • Kitchenware
    • Layout
      • New Layout
      • Legacy Layout
    • Components
      • Announcement
      • Banner Carousel
      • Banner With Products Carousel
      • Blog Category List
      • Blog List
      • Brand List
      • Brands Carousel
      • Breadcrumb
      • Call To Action
      • Cart
      • Categories List
      • Change Password
      • Checkout
      • Cookie Manager
      • Filter list
      • Footer
      • Forgot Password
      • Form
      • Hero Carousel
      • Icon Block
      • Invitation
      • Last Visited Products
      • Layout
      • Login
      • Map
      • Nav Bar
      • Offer
      • Product Attachments
      • Product Attributes
      • Product Documentation
      • Product Expected
      • Product Modal
      • Products Block
      • Products Carousel
      • Product Single
      • Profile
      • Quote
      • Register
      • Related Products
      • Search
      • Stores
      • Subscribe Newsletter
      • Text with Image
      • Top Bar
      • Video
    • Reusables
      • Getting Started
    • Assets
      • Getting Started
    • SDK
      • Products
        • _findProductsByCategory
        • _findProductsByIds
        • _findProductsByTitle
        • _findProductsByFilter
        • _findProductsByCriteria
        • _findProductsAndCalculate
        • _findProductsThenCalculate
        • _getProductAttributeSet
        • _setLastVisited
      • Categories
        • _findCategoryTreeById
        • _findCategoriesByIds
        • _findCategoryByAlias
        • _findCategoryTreeByAlias
        • _getCategoryContent
      • Collections
        • _getCollectionContent
        • _findCollectionsByIds
        • _findCollectionsByIdsThenCalculate
      • Brands
        • _getBrandContent
        • _findBrandsByIds
      • Cart
        • _addToCartMulti
        • _addToCart
        • _setCart
        • _clearCart
        • _setCartListener
        • _removeFromCart
        • _calculateCart
      • Checkout
        • _startCheckout
        • _updateCheckout
        • _completeCheckout
      • Shopping Lists
        • _getShoppingLists
        • _updateShoppingList
        • _createShoppingList
        • _deleteShoppingList
        • _getShoppingListByAlias
      • Navigation
        • _getFooterMenu
        • _getHeaderMenu
      • Users
        • _getUserById
      • Utils
        • _calculateCurrency
        • _getCurrencySymbol
        • _getCulture
        • _subscribeToNewsletter
        • _findUnitsByIds
  • Noir
    • 0. Introduction
    • 6. FAQ
    • 1. Structure
      • _Overview
      • LayoutA.liquid
      • ComponentsList.liquid
      • Metas.liquid
      • CssVariables.liquid
      • Json.liquid
      • GoogleTagManager.liquid
      • StagingButton.liquid
    • 2. Components
      • _Overview
      • Announcement
      • BannerCarousel
      • BlogCategoryList
      • BlogList
      • BrandList
      • Breadcrumb
      • Cart
      • CategoriesList
      • ChangePassword
      • Checkout
      • CookieManager
      • FilterList
      • Footer
      • ForgotPassword
      • Form
      • IconBlock
      • Invitation
      • LastVisitedProducts
      • Login
      • Map
      • NavBar
      • Offer
      • ProductAttachments
      • ProductAttributes
      • ProductComparison
      • ProductDocumentation
      • ProductMixList
      • ProductsBlock
      • ProductsCarousel
      • ProductSingle
      • Profile
      • Quote
      • Register
      • RelatedProducts
      • SingleBlog
      • Stores
      • TextWithImage
      • ThankYouPage
      • TopBar
      • Wishlist
    • 3. Reusables
      • _Overview
      • Addresses
      • AddressForm
      • AnnouncementModal
      • BackToTop
      • BillingRetail
      • BlogPostingStructuredData
      • BrandListStructuredData
      • CollectionStructuredData
      • Company
      • General
      • Login
      • LoginModal
      • MonthlyTransactions
      • Offers
      • Orders
      • Payment
      • ProductAttachments
      • ProductAttributes
      • ProductComparisonButton
      • ProductComparisonFloatingButton
      • ProductGridItem
      • ProductGridItemClassic
      • ProductListItem
      • ProductModal
      • ProductStructuredData
      • ProfileInfo
      • PromptModal
      • Quotes
      • Register
      • Services
      • Shipping
      • ShoppingLists
      • ShoppingListsButton
      • ShoppingListsNavbar
      • StoresStructuredData
      • Toast
      • Transactions
      • Users
      • VariantContent
      • VariantContentClassic
      • WishlistButton
    • 4. Assets
      • Fonts
      • Images
      • Templates
      • Javascript
        • _Overview
        • theme.js
      • Css - Scss
        • _Overview
        • ThemeClasses
    • 5. SDK
      • _Overview
      • LiquidGlobals
      • ServicesSDK
  1. 3. Reusables

Services

Purpose#

Services is the theme’s client-side service layer that centralizes API calls and shared storefront workflows.
It exposes servicesreusabledefault as the common SDK used by components/reusables for cart, checkout, profile, offer, and payment operations.

Where it's rendered#

No direct Liquid render call was found for Reusables/Services/Default in this workspace.

Inputs (Liquid render parameters)#

This reusable is rendered without Liquid parameters.

Template behavior (Liquid + Alpine)#

This reusable does not render UI.
Its role is to register the global JavaScript object servicesreusabledefault, which is then consumed by other components and reusables.

Data contract (JS runtime)#

Document runtime state shape, factories, and main state fields.

JavaScript#

Standard function conventions#

1) Pattern: Axios + normalized return#

Most methods follow this structure:
1.
Call an endpoint using axios.get/post/put/delete.
2.
Normalize the response via:
getAxiosResponse(response, context)
3.
Return the normalized object:
4.
On exceptions:
Log with a method-specific console.error('<method> failed:', e)
Return e.response (raw Axios error response), or return the cancel error when using cancel tokens.

2) Context strings#

getAxiosResponse is always called with a stable context string (usually the method name), e.g.:
this.getAxiosResponse(response, 'addToCart')
This makes error logs searchable and consistent.

3) Cancellation#

Some methods cancel the previous request before starting a new one, using:
axios.CancelToken.source()
The service caches Axios CancelToken sources on internal properties of the services object.

4) Side effects#

Several methods intentionally do more than “just call an API”. Common side effects include:
Updating localStorage (cartToken, checkoutToken, cartData)
Calling setCookie(...)
Updating Alpine stores:
Alpine.store('cart').update(...)
Alpine.store('checkout').set(...)
Alpine.store('checkout').validateStep(...)
Alpine.store('checkout').isUpdating = true/false
Alpine.store('modal').shouldReinitialize = true

5) fetch vs axios#

Some search endpoints use fetch(...) and return raw JSON (not the normalized wrapper). These are exceptions and are documented explicitly below.

API reference (grouped by category)#

General#

getCartData#

clearCart#

teardownKlarnaPayments#

uuidv4#

completeCheckout#

fetchUsers#

deleteCompanyLogo#

getCartData()#

Fetches the current cart payload for the active session.
Notes:
Used by cart/checkout-related flows to refresh cartData after mutations.
Returns a normalized response (via getAxiosResponse).

teardownKlarnaPayments()#

Performs cleanup for Klarna Payments UI state.
Notes:
Intended to be called when leaving a Klarna step / when re-initializing checkout payment forms.
This method may interact with payment-specific globals/scripts loaded in the layout.

getAxiosResponse(response, context = "")#

Normalizes an Axios response into a stable shape.
Parameters:
response: Axios response object (or falsy).
context: optional string used in logs.
Behavior:
If response.status is not 2xx, logs a structured error and returns:
{ success: false, status, error: response }
If 2xx, returns:
{ success: true, status, data: response.data }

uuidv4()#

Generates a random GUID-like string using crypto.getRandomValues.
Used for:
checkoutToken generation
file upload session ids

setShopranosCookie(value, expiresAt)#

POST /api/cookies.
Parameters:
value: cookie value.
expiresAt: expiration date/time.
Returns:
normalized response via getAxiosResponse.

internalUploadFile(file, url, endpoint = null)#

Uploads a file in chunks (200000 bytes per chunk) using fetch and FormData.
Parameters:
file: a File object.
url: base upload URL.
endpoint: optional extra query param ?endpoint=....
Returns:
guid (string) for the upload session, or null on failure.
Notes:
Uses uuidv4() internally.
Does not use axios.

generateTextFromAI(data, cultureCode, currency)#

POSTs product-offer prompt payload to /api/ai/product/offer/notes and returns normalized response.

fetchProductMixProducts(params)#

GET /api/product-mix/my-list?{params} and returns normalized response.

Shopping Lists#

getShoppingLists#

getShoppingLists()#

GET /api/ShoppingList.
Side effects:
Alpine.store('modal').shouldReinitialize = true.
Returns normalized response.

createShoppingList(data)#

POST /api/ShoppingList.
Parameters:
data: request payload (shopping list creation model).
Returns normalized response.

deleteShoppingList(alias)#

DELETE /api/ShoppingList/{alias}.
Parameters:
alias: shopping list alias.
Returns normalized response.

updateShoppingList(list)#

PUT /api/ShoppingList/{list.alias}.
Parameters:
list: full list object; must include alias.
Returns normalized response.

importShoppingList(alias, file)#

Imports items into an existing list.
Steps:
1.
Uploads the file via internalUploadFile(file, '/api/file') → returns guid
2.
POST /api/ShoppingList/import-items/{alias}/{guid}
Parameters:
alias: list alias.
file: import file.
Returns normalized response.

exportShoppingList(alias)#

Exports items to a file.
POST /api/ShoppingList/export-items/{alias} with { responseType: 'blob' }.
Creates a browser download named ShoppingList-{alias}.xlsx.
Parameters:
alias: list alias.
Returns normalized response.

Wishlist#

clearWishlist#

clearWishlist()#

DELETE /api/wishlist/items.
Returns normalized response.

addItemToWishlist(productId)#

POST /api/wishlist/items/products/{productId}.
Parameters:
productId: product id.
Returns normalized response.

removeItemFromWishlist(productId)#

DELETE /api/wishlist/items/products/{productId}.
Parameters:
productId: product id.
Returns normalized response.

Navbar (Search + announcements)#

findProductsByCriteria(searchCriteria)#

Performs a product search using fetch.
Endpoint: GET /api/products/liquid with query string params.
Parameters:
searchCriteria: object of query params. Only non-null/undefined values are included.
Returns:
object | null
Returns parsed JSON on success.
Returns null and logs on non-OK response.

findProductsByCriteriaExtended(searchCriteria)#

Like findProductsByCriteria but uses:
GET /api/products/search-extended
Parameters:
searchCriteria: object of query params.
Returns:
parsed JSON.
Errors:
Throws an Error when the response is not OK.

setReadAnnouncementIds(ids)#

POST /api/announcements.
Parameters:
ids: array/payload containing announcement ids.
Returns normalized response.

Form#

sendEmail(data)#

Sends the contact form to the backend.
Uploads file fields first (where field.type == 4).
POST /api/contact.
Parameters:
data: contact form payload; expected to include fields[].
Returns normalized response.

internalUploadFiles(fields)#

Uploads contact form files for a set of form fields.
Parameters:
fields: list of field definitions.
Behavior:
Reads files from DOM input document.getElementById(field.name).files.
Uploads each file via uploadContactFormFile(file).
Writes back field.value as a comma-joined list of returned GUIDs.

uploadContactFormFile(file)#

Uploads a single contact-form file.
Calls internalUploadFile(file, '/api/file/contact').
Returns:
guid string or null.

Profile (Account, addresses, managed users)#

accountForgotPassword(data)#

POST /api/account/forgotpassword.
Parameters:
data: forgot password payload.
Returns normalized response.

changePassword(data)#

POST /api/account/changepassword.
Parameters:
data: change password payload.
Returns normalized response.

changePasswordProfile(data)#

POST /api/account/changeprofilepassword.
Parameters:
data: profile password change payload.
Returns normalized response.

updateUserProfile(data)#

PUT /api/account/updateuserinfo.
Parameters:
data: user profile payload.
Returns normalized response.

createUserAddress(data)#

POST /api/customer/addresses.
Parameters:
data: address payload.
Returns normalized response.

updateUserAddress(data, addressId)#

PUT /api/customer/addresses/{addressId}.
Parameters:
data: address payload.
addressId: address id.
Returns normalized response.

deleteUserAddress(addressId)#

DELETE /api/customer/addresses/{addressId}.
Parameters:
addressId: address id.
Returns normalized response.

setUserAddressAsPrimary(addressId)#

POST /api/customer/addresses/setdefault/{addressId}.
Parameters:
addressId: address id.
Returns normalized response.

accountLogin(data)#

POST /api/account/login.
Parameters:
data: login payload.
Side effects on success (status == 200):
GET /api/cart/user to retrieve a user cart.
Sets localStorage.cartToken, cookie cartToken, and localStorage.cartData.
Returns normalized response.

accountLoginWithCustomerId(customerId)#

Step 2 of the multi-customer login flow. Called after accountLogin when a user has multiple customer memberships and must select which customer to log in as.
POST /api/account/login/{customerId}.
Parameters:
customerId: the selected customer id.
Side effects on success (status == 200):
GET /api/cart/user to retrieve the user cart for the selected customer.
Sets localStorage.cartToken, cookie cartToken, and localStorage.cartData.
Returns normalized response.

accountRegister(data)#

POST /api/account/register.
Parameters:
data: register payload.
Returns normalized response.

registerUser(data, token)#

POST /api/account/confirmInvitation/{token}.
Parameters:
data: registration payload.
token: invitation token.
Returns normalized response.

deleteUser(user)#

DELETE /api/managedusers/{user.id}.
Parameters:
user: object with at least id.
Returns normalized response.

updateUser(user)#

PUT /api/managedusers/{user.id}.
Parameters:
user: user object (must include id).
Returns normalized response.

inviteUser(data)#

POST /api/managedusers/invite.
Parameters:
data: invite payload.
Returns normalized response.

fetchUsers()#

GET /api/managedusers with params:
page: 1
pageSize: 12
Returns normalized response.

uploadCompanyLogo(file, customerId)#

Uploads a company logo.
Steps:
1.
Uploads the file via internalUploadFile(file, '/api/file', '/api/files/upload/logo/{customerId}')
2.
PUT /api/customer/logo
Parameters:
file: logo file.
customerId: customer id.
Returns normalized response.

deleteCompanyLogo()#

DELETE /api/customer/logo.
Returns normalized response.

Cart#

addToCart(productId, variantId, quantity, finalPrice, originalPrice, showPopUp = true)#

Adds a single item to the cart.
Endpoint:
POST /api/cart/{cartToken}/add
Parameters:
productId: product id.
variantId: product variant id.
quantity: quantity to add.
finalPrice: used for GA payload (price).
originalPrice: used for GA payload (initialPrice).
showPopUp: passed to $store.cart.update(...) to control UI feedback.
Preconditions / side effects:
Cancels previous cart update via cancelTokenSource.
Ensures localStorage.checkoutToken exists (creates one via uuidv4() and sets cookie checkoutToken).
Updates localStorage.cartToken + cookie cartToken.
If $store.cart exists, calls:
Alpine.store('cart').update(cartData, [{ ...addedItem, addedQuantity: quantity }], showPopUp)
If cart has items, sends GA event addToCart.
Returns normalized response.

addMultipleToCart(variations, showPopUp = true)#

Adds multiple items to cart in one request.
Endpoint:
POST /api/cart/{cartToken}/addmultiple
Parameters:
variations: array of objects with at least:
productId
productVariantId
quantity
dim1Value, dim2Value
price, initialPrice
showPopUp: passed to cart store update.
Side effects:
Updates token/cookie.
Updates $store.cart once with successfully added products.
Sends GA addToCart event.
Returns normalized response.

updateProductCart(cartData, cancelToken)#

Updates the cart.
Endpoint:
PUT /api/cart/{cartToken}
Parameters:
cartData: cart update payload.
cancelToken: Axios cancel token.
Side effects:
Updates token/cookie.
Calls Alpine.store('cart').update(cartData).
Returns normalized response (or cancel error).

updateProductQuantity(data, cancelToken)#

Validates/resolves requested quantity.
Endpoint:
POST /api/cart/{cartToken}/resolveQuantity
Parameters:
data: object with:
productId
productVariantId
requestedQuantity
cancelToken: Axios cancel token.
Returns normalized response (or cancel error).

clearCart()#

Clears all cart items.
Endpoint:
DELETE /api/cart/{cartToken}/all
Side effects:
Sends GA removeFromCart based on stored localStorage.cartData.
Updates token/cookie.
Calls Alpine.store('cart').update(cartData).
Returns normalized response.

removeFromCart(variantId)#

Removes an item by variant id.
Endpoint:
DELETE /api/cart/{cartToken}/{variantId}
Parameters:
variantId: product variant id.
Side effects:
Sends GA removeFromCart for the removed line.
Updates token/cookie.
Calls Alpine.store('cart').update(cartData).
Returns normalized response.

getCartValidation()#

Fetches calculated cart validation and returns a simplified error summary.
Endpoint:
GET /api/cart/calculated/{cartToken}/
Cancellation:
Cancels the previous calculation request using calculatecartCancelTokenSource.
Returns:
On success: { isSuccess, lines: [{ type, count, lineIds[] }] }
On failure: returns e.response.

importCart(type, file)#

Imports cart lines from a CSV/Excel file using chunked upload.
Endpoint:
POST /api/cart/import?format={type}
Parameters:
type: import format (for example Csv or Excel).
file: File, FileList, or array-like file input; the first valid File is used.
Behavior:
Splits the file into 200000-byte chunks and posts each chunk with FormData.
Uses Axios option validateStatus: () => true so 202 chunk-accepted and final 200 responses are handled explicitly by the method.
Returns early for non-200/202 responses.
validateStatus#
importCart(...) sets Axios validateStatus: () => true so chunk responses are not rejected by Axios and can be handled explicitly in code (202 continue, 200 final payload, other statuses return early).
Side effects on success:
When payload contains cart.token, updates localStorage.cartToken and cookie cartToken.
Returns:
Final import payload on success, or e.response on failure.

exportCart(type)#

POST /api/cart/export with the selected format and triggers file download from the returned URL.

Quantity Constraints (Progressive Hydration)#

Product cards (grid, list, classic) request personalized quantity constraints client-side so the server can render from a cached, personalization-free view model. All calls that happen in the same browser tick are batched into a single request.

hydrateProductConstraints(product)#

Enqueues product for constraints hydration and returns a Promise that resolves once the shared batch completes.
Requires product.id and a non-empty product.productVariants[].
Schedules a setTimeout(..., 0) flush on first call per tick so all cards on the same page share one request.
On resolution, writes variant.quantityConstraints for each variant in the product.
On failure, falls back to _applyDefaultConstraints(product).
POST /api/cart/quantity-constraints/by-products — body is an array of product ids.

_applyDefaultConstraints(product)#

Writes permissive fallback constraints (min: 1, max: 999999, step: 1, isValid: true) to every variant of product.
Called automatically by hydrateProductConstraints on network failure, or directly by callers that need an immediate safe default.

Checkout#

updateCheckout(data, checkoutStep = null)#

Updates checkout.
Endpoint:
POST /api/checkout/update/{checkoutToken}
Parameters:
data: checkout update payload.
checkoutStep: optional string; when present, triggers step validation.
Side effects:
Injects data.cartItems = Alpine.store('cart').items.
Toggles Alpine.store('checkout').isUpdating.
On success:
Alpine.store('checkout').set(returnResponse.data)
Alpine.store('checkout').validateStep(checkoutStep, true)
On error:
Alpine.store('checkout').globalError = true
validateStep(checkoutStep, false)
Returns normalized response.

proceedToCheckout(data)#

High-level checkout continuation.
Behavior:
Calls updateCheckout(data).
If there is a payment provider, calls initiatePayment(checkoutData).
Otherwise calls completeCheckout().
Returns normalized response.

initiatePayment(data)#

Initiates payment and performs provider-specific redirects.
Endpoint:
POST /api/payment/initiate/{checkoutToken}
Parameters:
data: checkout data; must contain data.payment.provider.
Behavior:
Redirects the browser when redirectUrl is returned for providers like PayPal/JCC/Stripe/Nexi.
Builds and auto-submits provider forms for EDPS/Epay/CardLink.
Injects and executes HTML snippet for Klarna.
Otherwise falls back to completeCheckout().
On errors:
Redirects to /checkout/error.

loadKlarnaPaymentsScript#

Loads or reuses the Klarna Payments script and resolves when the script is ready.

buildKlarnaPaymentsContainer#

Builds/returns the DOM container used to host Klarna embedded payment content.

showKlarnaPaymentsError#

Displays/logs a Klarna-specific error state for failed setup/authorization steps.

cancelKlarnaPayments#

Cancels/tears down any in-flight Klarna UI/payment state.

handleKlarnaPayments#

Coordinates Klarna payment flow selection and delegates to inline/HPP handlers.

handleKlarnaPaymentsInLine#

Initializes and runs the embedded (inline) Klarna flow.

handleKlarnaPaymentsHpp#

Initializes and runs the hosted payment page (HPP) Klarna flow.

postKlarnaPaymentsAuthorize#

Submits Klarna authorization payload and returns the backend authorization result.

completeCheckout()#

Completes checkout.
POST /api/checkout/complete/{checkoutToken}.
Returns normalized response.

fetchPostalCodes(countryCode)#

Fetches postal codes.
GET /api/location/postalcodes/{countryCode}.
Parameters:
countryCode: country code.
Returns normalized response.

Pricing (Progressive Hydration)#

The server renders product cards/lists from a cached, personalization-free view model. hydrateProductPrices batches per-card requests into a single page-level call so every card gets its personalized/ERP price without one request per card.

hydrateProductPrices(product)#

Enqueues a product for personalized price hydration and returns a Promise that resolves once the shared page-level batch completes.
No-ops (resolves false immediately) when product/product.id is missing or product.productVariants is empty.
Pushes { product, resolve } onto an internal _priceBatch.queue and schedules a single _flushPriceBatch() call via setTimeout(..., 0) — every card that calls this in the same tick shares one flush.
Key behaviors / edge cases
_flushPriceBatch() dedupes product ids across the batch, sends them in one POST /api/pricing/catalog/calculate/by-products request, and distributes the returned per-product price aggregate back to each queued card.
Logs a console error and resolves false for the whole batch if the request itself fails; resolves false for individual cards whose id isn't present in the response.

Thank You#

triggerOrderViewedCleanup(orderId)#

Triggers analytics cleanup after the thank-you page is viewed.
POST /api/order/{orderId}/analytics/thank-you-page-viewed
Parameters:
orderId: order id.
Returns normalized response.

Offers / Quotes#

updateOfferPricing#

Updates offer pricing (line-level or aggregate) and returns normalized response.

createOffer#

Creates a new offer and returns normalized response.

updateOffer#

Updates an existing offer and returns normalized response.

rejectOffer#

Rejects/cancels an existing offer and returns normalized response.

createQuote#

Creates a quote payload/workflow entry and returns normalized response.

Global Alpine stores#

This reusable may update these stores when they exist (depending on the called method):
$store.cart
$store.checkout
$store.modal
$store.toast (indirectly; most callers handle toasts themselves)

Services / API calls#

This reusable is the services layer itself.
It calls backend endpoints under /api/... via axios (mostly) and fetch (in specific search endpoints).

Dependencies#

JS: Reusables/Services/Default.js
Translations: Reusables/Services/Default.json

Notes#

servicesreusabledefault includes both:
“thin” API wrappers (call endpoint + normalize)
“orchestrators” that update stores/local storage and trigger GA events.
Modified at 2026-07-24 07:29:51
Previous
Register
Next
Shipping
Built with