Webviews embedded in the cart of Associate App receive a live snapshot of the cart from the app and can post messages back to trigger native app actions. Use them to surface information next to the items the associate is selling — for example a loyalty enrollment prompt, available coupons from an external promotion engine, warranty validation of scanned serial numbers, or brand-specific purchase advisories.
Available from Associate App v1.83.0
Cart webview slots and the
meta.allowExpansionoption are available from Associate App version 1.83.0
Further reading
Adding webview customizations to the product detail page — The same mechanism on the PDP, including the full postMessage reference.
Adding webview customizations using external authentication — Setting up external identity providers and reading context in any Associate App webview.
Slots
Two slots are available in the cart. Configure which slot the webview appears via the Customization Configuration API.
Slot ID | Position |
|---|---|
| Top of the cart, below the customer and address cards, above the item list |
| Bottom of the cart, above the totals summary |
One slot can host multiple customizations, and they are rendered in configuration order.
Note
Cart slots only render when the cart contains at least one item. An empty cart shows the standard empty-cart screen without any customizations. When the cart has items, an enabled inline webview always renders and reserves its configured
meta.height. Design your page to display a sensible empty or collapsed state when it has nothing to display.
Configuring a cart webview
Send a PUT request to the Customization Configuration API. The customization_id in the path is provided by you, to generate a UUID.
{
"enabled": true,
"type": "webview",
"slot": "cart_top",
"label": "Loyalty",
"title": "Loyalty",
"caption": "Open",
"url": "https://your-webview-url.com/loyalty",
"meta": {
"inline": true,
"scrollEnabled": false,
"height": 150
}
}Display modes
Webviews can be configured as:
Full-screen (default) — Opens as a new screen when the associate taps a button in the cart
Inline — Rendered directly within the cart. Set
meta.inline: truein the configuration, along withmeta.height(pixels), and optionallymeta.scrollEnabled,meta.scrollXEnabled,meta.scrollYEnabled.
Available from Associate App v1.83.0
An inline webview displays a header with the configured title and a button (labeled with caption) that opens the same page in full-screen mode. To hide that button and keep the webview inline-only, set meta.allowExpansion: false. The allowExpansion property defaults to true. Only an explicit false value hides the button.
For the full display mode reference and code examples, see Adding webview customizations to the product detail page.
{
"meta": {
"inline": true,
"height": 180,
"allowExpansion": false
}
}Delivering context
When the app renders the webview, it adds a base64-encoded JSON payload to the URL as a fragment (#):
https://your-webview-url.com/page#<base64-encoded-JSON>Decode and parse it on the client side:
const raw = decodeURIComponent(window.location.hash.slice(1))
const context = JSON.parse(atob(raw))The context object has the following payload:
{
contextProps: {
formData: {
// --- Cart snapshot ---
cart: {
items: Array<{
productId: string
itemIds: string[] // Cart line item IDs — use with the Cart API
quantity: number
unitPrice: number
itemDiscount: number
externalIdentifiers: Array<{
serialNumber: string | null
epc: string | null
}>
}>
grandTotal: number
subtotal: number
discountTotal: number
taxTotal: number
remainingAmount: number
currency: string | null
coupons: string[] // Applied coupon codes
customerId: string | null // Customer assigned to the cart, if any
}
// --- Session fields (always present) ---
associateId: string // ID of the logged-in associate
storeId: string // ID of the current store
cartId: string // Active cart ID
}
}
auth: {
accessToken: string // NewStore access token — use to call NewStore APIs
}
externalIdentities: Array<{
identityProvider: string
identity: string
}>
theme: object // App color, spacing, and typography tokens
dimensions: { top: number, bottom: number, left: number, right: number }
enums: { DocumentType: object } // Print document type constants
securityToken: string // One-time token generated per webview session
}Privacy
The cart snapshot deliberately contains no customer PII, such as a name, email address, or postal address. Use
customerIdtogether withauth.accessTokento fetch more customer data from NewStore APIs when you need it.
Reacting to cart changes
The app re-serializes the payload whenever the cart changes, such as when the associate scans another item or applies a discount. Read the fragment at load time and listen for the hashchange event:
function render() {
const context = getWebViewContext()
if (!context) return
const { cart } = context.contextProps.formData
// update your UI from the fresh snapshot
}
window.addEventListener('hashchange', render)
render()Whether an update arrives as a soft navigation or a page reload is platform-dependent. Handle both by keeping the render() property idempotent.
Making a call to NewStore APIs
Use auth.accessToken to make authenticated calls to NewStore APIs. For example, attaching a warranty add-on to an item already in the cart via the Cart Line Item API:
const { auth, contextProps: { formData } } = context
const baseUrl = `https://<tenant>.p.newstore.net/v0/d`
await fetch(`${baseUrl}/checkout/carts/${formData.cartId}/items/${formData.cart.items[0].itemIds[0]}/add-ons`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${auth.accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
product_id: '<warranty-product-id>',
fulfillment: 'IN_STORE_HANDOVER',
price: { source: 'INTERNAL', source_id: '<pricebook-id>' },
}),
})After the webview modifies the cart, trigger Associate App to reload the cart view so the associate sees the change immediately:
window.open(`com.newstore.associate-one://cart/load?cartId=${formData.cartId}`)Posting messages back to the app
The webview can trigger native app actions via window.ReactNativeWebView.postMessage. The same messages are available as on the product detail page. See the full postMessage reference:
// Close a full-screen webview
window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'close' }))
// Open an https:// URL in the system browser
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'openExternalUrl',
message: { url: 'https://...' }
}))
// Print a document
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'print',
message: { resources: [{ documentType: context.enums.DocumentType.salesReceipt, url: 'https://...' }] }
}))What cart webviews cannot do
A cart webview is informational and additive: it can display content and call NewStore APIs, but it cannot block the checkout flow or prevent the associate from completing a sale. If your use case requires enforcement, such as for legally binding quantity restrictions per brand, you must implement it in backend order validation in addition to the in-cart advisory.
Inline webviews require network connectivity and do not render meaningful content when the device is offline.
Example: loyalty enrollment banner
A minimal cart_top page that shows how many points the current purchase would earn:
function getWebViewContext() {
const hash = window.location.hash.slice(1)
if (!hash) return null
try {
return JSON.parse(atob(decodeURIComponent(hash)))
} catch {
return null
}
}
function render() {
const context = getWebViewContext()
if (!context) return
const { cart } = context.contextProps.formData
const points = Math.round((cart.grandTotal || 0) * 10)
document.getElementById('root').textContent = cart.customerId
? `This purchase earns ${points} points for the customer on the cart.`
: `Add the customer to the cart to earn ${points} points on this purchase.`
}
window.addEventListener('hashchange', render)
render()