@liquidcommerce/elements-sdk 2.7.21 → 2.7.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.checkout.esm.js +7176 -7115
- package/dist/index.esm.js +11572 -11515
- package/dist/types/core/pubsub/interfaces/address.interface.d.ts +3 -0
- package/dist/types/core/pubsub/interfaces/core.interface.d.ts +2 -2
- package/docs/v1/api/actions/address-actions.md +20 -15
- package/docs/v1/api/actions/cart-actions.md +22 -23
- package/docs/v1/api/actions/checkout-actions.md +72 -25
- package/docs/v1/api/actions/product-actions.md +61 -15
- package/docs/v1/api/client.md +38 -14
- package/docs/v1/api/configuration.md +5 -1
- package/docs/v1/api/injection-methods.md +8 -4
- package/docs/v1/api/typescript-types.md +6 -0
- package/docs/v1/examples/advanced-patterns.md +7 -6
- package/docs/v1/examples/checkout-flow.md +1 -2
- package/docs/v1/getting-started/concepts.md +20 -25
- package/docs/v1/getting-started/installation.md +4 -4
- package/docs/v1/guides/address-component.md +12 -8
- package/docs/v1/guides/best-practices.md +5 -5
- package/docs/v1/guides/cart-component.md +27 -39
- package/docs/v1/guides/checkout-component.md +27 -29
- package/docs/v1/guides/events.md +4 -4
- package/docs/v1/guides/product-component.md +42 -19
- package/docs/v1/guides/product-list-component.md +8 -9
- package/docs/v1/guides/theming.md +6 -9
- package/docs/v1/integration/proxy-setup.md +22 -5
- package/docs/v1/reference/browser-support.md +2 -1
- package/docs/v1/reference/error-handling.md +12 -7
- package/docs/v1/reference/performance.md +1 -3
- package/docs/v1/reference/troubleshooting.md +3 -3
- package/package.json +8 -17
|
@@ -103,6 +103,10 @@ interface ILiquidCommerceElementsConfig {
|
|
|
103
103
|
}
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
+
### ILiquidCommerceElementsBuilderConfig
|
|
107
|
+
|
|
108
|
+
Same shape as `ILiquidCommerceElementsConfig`, used by `ElementsBuilder()`.
|
|
109
|
+
|
|
106
110
|
### ILiquidCommerceElementsCheckoutClientConfig
|
|
107
111
|
|
|
108
112
|
Same shape as `ILiquidCommerceElementsConfig`, used for the checkout-only client.
|
|
@@ -135,6 +139,7 @@ interface IElementsProxyConfig {
|
|
|
135
139
|
interface ILiquidCommerceElementsDevelopmentConfig {
|
|
136
140
|
customApiUrl?: string;
|
|
137
141
|
openShadowDom?: boolean;
|
|
142
|
+
mockMode?: boolean; // when true, sends an 'X-Liquid-Api-Mock-Mode' header to receive mock data
|
|
138
143
|
}
|
|
139
144
|
```
|
|
140
145
|
|
|
@@ -215,6 +220,7 @@ type PLCProductUrl = string | Record<string, string>;
|
|
|
215
220
|
interface IInjectProductListSearchParams {
|
|
216
221
|
containerId: string;
|
|
217
222
|
slug: string;
|
|
223
|
+
filters?: ProductListFilterType[];
|
|
218
224
|
}
|
|
219
225
|
```
|
|
220
226
|
|
|
@@ -28,7 +28,8 @@ await window.LiquidCommerce.elements.actions.address.setAddressManually(
|
|
|
28
28
|
two: 'Apt 4',
|
|
29
29
|
city: 'New York',
|
|
30
30
|
state: 'NY',
|
|
31
|
-
zip: '10001'
|
|
31
|
+
zip: '10001',
|
|
32
|
+
country: 'US'
|
|
32
33
|
},
|
|
33
34
|
{
|
|
34
35
|
latitude: 40.7128,
|
|
@@ -49,17 +50,17 @@ await window.LiquidCommerce.elements.actions.address.setAddressManually(
|
|
|
49
50
|
|
|
50
51
|
```javascript
|
|
51
52
|
window.addEventListener('lce:actions.product_loaded', (event) => {
|
|
52
|
-
const { identifier, name,
|
|
53
|
+
const { identifier, name, priceInfo } = event.detail.data;
|
|
53
54
|
gtag('event', 'view_item', {
|
|
54
|
-
items: [{ item_id: identifier, item_name: name, price:
|
|
55
|
+
items: [{ item_id: identifier, item_name: name, price: (priceInfo?.minimum ?? 0) / 100 }]
|
|
55
56
|
});
|
|
56
57
|
});
|
|
57
58
|
|
|
58
59
|
window.addEventListener('lce:actions.checkout_submit_completed', (event) => {
|
|
59
|
-
const {
|
|
60
|
+
const { orderNumber, orderTotal } = event.detail.data;
|
|
60
61
|
gtag('event', 'purchase', {
|
|
61
|
-
transaction_id:
|
|
62
|
-
value:
|
|
62
|
+
transaction_id: orderNumber,
|
|
63
|
+
value: orderTotal / 100,
|
|
63
64
|
currency: 'USD'
|
|
64
65
|
});
|
|
65
66
|
});
|
|
@@ -60,14 +60,13 @@ When users click checkout, the cart redirects to your hosted checkout page with
|
|
|
60
60
|
data-liquid-commerce-elements
|
|
61
61
|
data-token="YOUR_API_KEY"
|
|
62
62
|
data-env="production"
|
|
63
|
-
data-checkout-container="checkout"
|
|
64
63
|
data-checkout-param="lce_checkout"
|
|
65
64
|
type="text/javascript"
|
|
66
65
|
src="https://elements.reservebar-worker.workers.dev/all/elements.js"
|
|
67
66
|
></script>
|
|
68
67
|
</head>
|
|
69
68
|
<body>
|
|
70
|
-
<div
|
|
69
|
+
<div data-lce-checkout></div>
|
|
71
70
|
</body>
|
|
72
71
|
</html>
|
|
73
72
|
```
|
|
@@ -96,12 +96,13 @@ The SDK uses a two-phase initialization strategy for optimal performance:
|
|
|
96
96
|
- Store initialization
|
|
97
97
|
- Theme setup
|
|
98
98
|
- Core component registration
|
|
99
|
+
- Telemetry / logger wiring
|
|
100
|
+
- Debug panel (if enabled)
|
|
99
101
|
|
|
100
|
-
**Phase 2: Deferred Services (
|
|
101
|
-
- Analytics
|
|
102
|
+
**Phase 2: Deferred Services (next macrotask, via `setTimeout(…, 0)`)**
|
|
103
|
+
- Analytics (Google Tag Manager)
|
|
102
104
|
- Cart pre-loading
|
|
103
105
|
- Heavy component registration
|
|
104
|
-
- Debug panel (if enabled)
|
|
105
106
|
|
|
106
107
|
This ensures fast initial page loads while still providing full functionality.
|
|
107
108
|
|
|
@@ -111,8 +112,8 @@ Listen for the client ready event to know when the SDK is initialized:
|
|
|
111
112
|
|
|
112
113
|
```javascript
|
|
113
114
|
window.addEventListener('lce:actions.client_ready', (event) => {
|
|
114
|
-
console.log('SDK version:', event.detail.version);
|
|
115
|
-
console.log('Ready at:', event.detail.timestamp);
|
|
115
|
+
console.log('SDK version:', event.detail.data.version);
|
|
116
|
+
console.log('Ready at:', event.detail.data.timestamp);
|
|
116
117
|
|
|
117
118
|
// Safe to use client
|
|
118
119
|
window.LiquidCommerce.elements.actions.cart.openCart();
|
|
@@ -207,18 +208,17 @@ The SDK maintains its own internal state for cart, checkout, and user data.
|
|
|
207
208
|
### Store Service
|
|
208
209
|
|
|
209
210
|
The SDK uses a centralized store service that:
|
|
210
|
-
- Maintains reactive state
|
|
211
|
+
- Maintains reactive state (in-memory, within a single tab)
|
|
211
212
|
- Persists data to localStorage
|
|
212
213
|
- Falls back to API storage
|
|
213
|
-
- Syncs across browser tabs
|
|
214
214
|
|
|
215
215
|
### State Persistence
|
|
216
216
|
|
|
217
217
|
**Cart State:**
|
|
218
218
|
- Saved to localStorage
|
|
219
219
|
- Persists across sessions
|
|
220
|
-
- Syncs across tabs automatically
|
|
221
220
|
- Survives page refreshes
|
|
221
|
+
- Other tabs pick up the persisted cart on their next load (no live cross-tab sync)
|
|
222
222
|
|
|
223
223
|
**Address State:**
|
|
224
224
|
- Saved when set by user
|
|
@@ -230,17 +230,9 @@ The SDK uses a centralized store service that:
|
|
|
230
230
|
- Exists during checkout flow
|
|
231
231
|
- Cleared after order completion
|
|
232
232
|
|
|
233
|
-
### Cross-Tab
|
|
233
|
+
### Cross-Tab Persistence
|
|
234
234
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
```javascript
|
|
238
|
-
// Tab 1
|
|
239
|
-
await window.LiquidCommerce.elements.actions.cart.addProduct([...]);
|
|
240
|
-
|
|
241
|
-
// Tab 2 automatically receives the update
|
|
242
|
-
// No additional code needed
|
|
243
|
-
```
|
|
235
|
+
State is persisted to `localStorage` keyed by device ID. The SDK does **not** register a `storage` listener, `BroadcastChannel`, or other inter-tab subscription, so there is **no live cross-tab synchronization** — a change made in one tab is only reflected in another already-open tab after that tab reloads (which re-runs the persisted-state load and re-fetches by the persisted cart ID).
|
|
244
236
|
|
|
245
237
|
## Component Lifecycle
|
|
246
238
|
|
|
@@ -269,10 +261,12 @@ Manual rerendering:
|
|
|
269
261
|
|
|
270
262
|
```javascript
|
|
271
263
|
const components = window.LiquidCommerce.elements.getInjectedComponents();
|
|
272
|
-
|
|
264
|
+
// The Map is keyed by the container ID passed to inject* (with any leading '#' stripped),
|
|
265
|
+
// not a '<type>-<index>' string. For a component injected into id="product":
|
|
266
|
+
const productComponent = components.get('product');
|
|
273
267
|
|
|
274
268
|
// Force rerender
|
|
275
|
-
productComponent
|
|
269
|
+
productComponent?.rerender();
|
|
276
270
|
```
|
|
277
271
|
|
|
278
272
|
### Component Removal
|
|
@@ -319,8 +313,9 @@ lce:forms.billing
|
|
|
319
313
|
|
|
320
314
|
```javascript
|
|
321
315
|
window.addEventListener('lce:actions.cart_item_added', (event) => {
|
|
322
|
-
console.log('Item added:', event.detail);
|
|
323
|
-
// {
|
|
316
|
+
console.log('Item added:', event.detail.data);
|
|
317
|
+
// event.detail is { data, metadata }; payload fields live under .data:
|
|
318
|
+
// { cartId, itemId, fulfillmentId, partNumber, quantity, engravingLines? }
|
|
324
319
|
});
|
|
325
320
|
```
|
|
326
321
|
|
|
@@ -332,14 +327,14 @@ The SDK is designed to fail gracefully and not crash your site.
|
|
|
332
327
|
|
|
333
328
|
### Error Isolation
|
|
334
329
|
|
|
335
|
-
SDK errors are
|
|
330
|
+
SDK errors are logged and also emitted as a `*_FAILED` event, then re-thrown so your code can catch them:
|
|
336
331
|
|
|
337
332
|
```javascript
|
|
338
|
-
//
|
|
333
|
+
// The SDK emits CART_PRODUCT_ADD_FAILED and re-throws, so this catch runs
|
|
339
334
|
try {
|
|
340
335
|
await window.LiquidCommerce.elements.actions.cart.addProduct([/* invalid data */]);
|
|
341
336
|
} catch (error) {
|
|
342
|
-
console.log('This error is
|
|
337
|
+
console.log('This error is re-thrown by the SDK and caught here');
|
|
343
338
|
}
|
|
344
339
|
|
|
345
340
|
// Your page keeps working
|
|
@@ -36,7 +36,7 @@ Add the following script tag to your page's `<head>` section:
|
|
|
36
36
|
|-----------|----------|-------------|
|
|
37
37
|
| `data-liquid-commerce-elements` | Yes | Identifies this as the Elements SDK script |
|
|
38
38
|
| `data-token` | Yes | Your LiquidCommerce API key |
|
|
39
|
-
| `data-env` |
|
|
39
|
+
| `data-env` | No | Environment: `development`, `staging`, or `production`. Defaults to `production` if omitted. |
|
|
40
40
|
| `defer` | Recommended | Allows non-blocking script loading |
|
|
41
41
|
|
|
42
42
|
### Where to Place the Script
|
|
@@ -73,7 +73,7 @@ If you only need checkout functionality (without product displays or cart), use
|
|
|
73
73
|
```html
|
|
74
74
|
<script
|
|
75
75
|
defer
|
|
76
|
-
data-liquid-commerce-elements
|
|
76
|
+
data-liquid-commerce-elements
|
|
77
77
|
data-token="YOUR_API_KEY"
|
|
78
78
|
data-env="production"
|
|
79
79
|
type="text/javascript"
|
|
@@ -245,7 +245,7 @@ The SDK accepts a configuration object during initialization:
|
|
|
245
245
|
|
|
246
246
|
```javascript
|
|
247
247
|
const client = await Elements('YOUR_API_KEY', {
|
|
248
|
-
env: 'production', //
|
|
248
|
+
env: 'production', // Optional (defaults to 'production'): 'development' | 'staging' | 'production'
|
|
249
249
|
debugMode: 'console', // Optional: 'none' | 'console' | 'panel'
|
|
250
250
|
customTheme: { /* ... */ }, // Optional: Theme customization
|
|
251
251
|
promoTicker: [ /* ... */ ], // Optional: Promo ticker configuration
|
|
@@ -293,7 +293,7 @@ If the SDK script fails to load:
|
|
|
293
293
|
If you see an error about Web Components:
|
|
294
294
|
|
|
295
295
|
```
|
|
296
|
-
[LiquidCommerce Elements] SDK requires support for Web Components
|
|
296
|
+
[LiquidCommerce Elements] SDK requires support for Web Components. Please include a Web Components polyfill for older browsers.
|
|
297
297
|
```
|
|
298
298
|
|
|
299
299
|
Include a Web Components polyfill before the SDK script:
|
|
@@ -34,10 +34,11 @@ Use the standalone address component when you need a dedicated address selection
|
|
|
34
34
|
```javascript
|
|
35
35
|
const client = await Elements('YOUR_API_KEY', { env: 'production' });
|
|
36
36
|
|
|
37
|
-
await client.injectAddressElement('address-container'
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
await client.injectAddressElement('address-container');
|
|
38
|
+
|
|
39
|
+
// React to address selection by listening for the address_updated event
|
|
40
|
+
window.addEventListener('lce:actions.address_updated', (event) => {
|
|
41
|
+
console.log('Address set:', event.detail.data);
|
|
41
42
|
});
|
|
42
43
|
```
|
|
43
44
|
|
|
@@ -67,10 +68,11 @@ For custom address flows without Google Places:
|
|
|
67
68
|
await window.LiquidCommerce.elements.actions.address.setAddressManually(
|
|
68
69
|
{
|
|
69
70
|
one: '123 Main Street',
|
|
70
|
-
two: 'Apt 4', // Optional
|
|
71
|
+
two: 'Apt 4', // Optional at runtime
|
|
71
72
|
city: 'New York',
|
|
72
73
|
state: 'NY',
|
|
73
|
-
zip: '10001'
|
|
74
|
+
zip: '10001',
|
|
75
|
+
country: 'US'
|
|
74
76
|
},
|
|
75
77
|
{
|
|
76
78
|
latitude: 40.7128,
|
|
@@ -85,6 +87,7 @@ await window.LiquidCommerce.elements.actions.address.setAddressManually(
|
|
|
85
87
|
- `city`: City name (required)
|
|
86
88
|
- `state`: Two-letter state code (required)
|
|
87
89
|
- `zip`: ZIP/postal code (required)
|
|
90
|
+
- `country`: Country code, e.g. `'US'` (required by the `IAddressAddress` type)
|
|
88
91
|
- `latitude`: Number between -90 and 90 (required)
|
|
89
92
|
- `longitude`: Number between -180 and 180 (required)
|
|
90
93
|
|
|
@@ -103,7 +106,8 @@ console.log(addressData);
|
|
|
103
106
|
// two: 'Apt 4',
|
|
104
107
|
// city: 'New York',
|
|
105
108
|
// state: 'NY',
|
|
106
|
-
// zip: '10001'
|
|
109
|
+
// zip: '10001',
|
|
110
|
+
// country: 'US'
|
|
107
111
|
// },
|
|
108
112
|
// coordinates: {
|
|
109
113
|
// latitude: 40.7128,
|
|
@@ -316,7 +320,7 @@ Addresses persist:
|
|
|
316
320
|
|
|
317
321
|
Addresses are:
|
|
318
322
|
- Stored locally in the browser
|
|
319
|
-
-
|
|
323
|
+
- Sent to LiquidCommerce servers for availability/product loading; the address id (with the cart id) may also be persisted server-side as a session fallback when localStorage is unavailable (and a delete request is sent when the address is cleared)
|
|
320
324
|
- Cleared when user logs out (if you implement logout handling)
|
|
321
325
|
|
|
322
326
|
## Best Practices
|
|
@@ -225,7 +225,7 @@ useEffect(() => {
|
|
|
225
225
|
// Update UI when cart changes
|
|
226
226
|
window.addEventListener('lce:actions.cart_updated', () => {
|
|
227
227
|
const cart = window.LiquidCommerce.elements.actions.cart.getDetails();
|
|
228
|
-
updateHeaderCartCount(cart.
|
|
228
|
+
updateHeaderCartCount(cart.itemCount);
|
|
229
229
|
});
|
|
230
230
|
```
|
|
231
231
|
|
|
@@ -233,18 +233,18 @@ window.addEventListener('lce:actions.cart_updated', () => {
|
|
|
233
233
|
|
|
234
234
|
```javascript
|
|
235
235
|
window.addEventListener('lce:actions.checkout_submit_completed', (event) => {
|
|
236
|
-
const {
|
|
236
|
+
const { orderNumber, orderTotal } = event.detail.data;
|
|
237
237
|
|
|
238
238
|
// Analytics
|
|
239
239
|
gtag('event', 'purchase', {
|
|
240
|
-
transaction_id:
|
|
241
|
-
value:
|
|
240
|
+
transaction_id: orderNumber,
|
|
241
|
+
value: orderTotal / 100
|
|
242
242
|
});
|
|
243
243
|
|
|
244
244
|
// Backend tracking
|
|
245
245
|
fetch('/api/track-order', {
|
|
246
246
|
method: 'POST',
|
|
247
|
-
body: JSON.stringify({
|
|
247
|
+
body: JSON.stringify({ orderNumber, orderTotal })
|
|
248
248
|
});
|
|
249
249
|
});
|
|
250
250
|
```
|
|
@@ -57,7 +57,7 @@ Show the number of items in the cart:
|
|
|
57
57
|
|
|
58
58
|
#### Floating Cart Button
|
|
59
59
|
|
|
60
|
-
Create a floating button (
|
|
60
|
+
Create a floating button (top-right corner):
|
|
61
61
|
|
|
62
62
|
```html
|
|
63
63
|
<script
|
|
@@ -174,9 +174,10 @@ await window.LiquidCommerce.elements.actions.cart.addProduct([
|
|
|
174
174
|
```
|
|
175
175
|
|
|
176
176
|
**Parameters:**
|
|
177
|
-
- `identifier` (string): Product UPC,
|
|
177
|
+
- `identifier` (string): Product UPC, size ID, or salsifyGrouping ID
|
|
178
178
|
- `fulfillmentType` (string): `'shipping'` or `'onDemand'`
|
|
179
179
|
- `quantity` (number): Number of items (default: 1)
|
|
180
|
+
- `engravingLines` (string[], optional): Engraving text lines for the product (applied when the product/variant supports engraving; ignored otherwise)
|
|
180
181
|
- Second parameter (boolean): Open cart after adding (default: false)
|
|
181
182
|
|
|
182
183
|
### Apply Promo Code
|
|
@@ -215,13 +216,12 @@ const cartData = window.LiquidCommerce.elements.actions.cart.getDetails();
|
|
|
215
216
|
console.log(cartData);
|
|
216
217
|
// {
|
|
217
218
|
// cartId: 'cart_abc123',
|
|
218
|
-
//
|
|
219
|
+
// promoCodeDiscount: 1000, // number | null
|
|
219
220
|
// subtotal: 9998, // in cents
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
//
|
|
223
|
-
//
|
|
224
|
-
// retailers: [...],
|
|
221
|
+
// itemCount: 5,
|
|
222
|
+
// items: {...}, // Record<itemId, ICartItem>
|
|
223
|
+
// retailers: {...}, // Record<retailerId, ICartRetailer>
|
|
224
|
+
// location: {...}, // or null
|
|
225
225
|
// ...
|
|
226
226
|
// }
|
|
227
227
|
```
|
|
@@ -282,8 +282,8 @@ Fired when cart data is loaded:
|
|
|
282
282
|
|
|
283
283
|
```javascript
|
|
284
284
|
window.addEventListener('lce:actions.cart_loaded', (event) => {
|
|
285
|
-
const { cartId,
|
|
286
|
-
console.log(`Cart loaded: ${
|
|
285
|
+
const { cartId, itemCount, subtotal } = event.detail.data;
|
|
286
|
+
console.log(`Cart loaded: ${itemCount} items, total: $${subtotal / 100}`);
|
|
287
287
|
});
|
|
288
288
|
```
|
|
289
289
|
|
|
@@ -305,8 +305,8 @@ Fired whenever cart contents change:
|
|
|
305
305
|
|
|
306
306
|
```javascript
|
|
307
307
|
window.addEventListener('lce:actions.cart_updated', (event) => {
|
|
308
|
-
const { cartId,
|
|
309
|
-
console.log('Cart updated:',
|
|
308
|
+
const { cartId, itemCount, subtotal } = event.detail.data.current;
|
|
309
|
+
console.log('Cart updated:', itemCount, 'items');
|
|
310
310
|
});
|
|
311
311
|
```
|
|
312
312
|
|
|
@@ -332,13 +332,13 @@ window.addEventListener('lce:actions.cart_item_removed', (event) => {
|
|
|
332
332
|
|
|
333
333
|
```javascript
|
|
334
334
|
window.addEventListener('lce:actions.cart_item_quantity_increase', (event) => {
|
|
335
|
-
const { cartId, itemId,
|
|
336
|
-
console.log(`Item ${itemId} quantity increased to ${
|
|
335
|
+
const { cartId, itemId, quantity } = event.detail.data;
|
|
336
|
+
console.log(`Item ${itemId} quantity increased to ${quantity}`);
|
|
337
337
|
});
|
|
338
338
|
|
|
339
339
|
window.addEventListener('lce:actions.cart_item_quantity_decrease', (event) => {
|
|
340
|
-
const { cartId, itemId,
|
|
341
|
-
console.log(`Item ${itemId} quantity decreased to ${
|
|
340
|
+
const { cartId, itemId, quantity } = event.detail.data;
|
|
341
|
+
console.log(`Item ${itemId} quantity decreased to ${quantity}`);
|
|
342
342
|
});
|
|
343
343
|
```
|
|
344
344
|
|
|
@@ -399,7 +399,7 @@ const client = await Elements('YOUR_API_KEY', {
|
|
|
399
399
|
},
|
|
400
400
|
layout: {
|
|
401
401
|
showQuantityCounter: true,
|
|
402
|
-
quantityCounterStyle: 'outlined', // or '
|
|
402
|
+
quantityCounterStyle: 'outlined', // or 'ghost'
|
|
403
403
|
drawerHeaderText: 'My Bag',
|
|
404
404
|
goToCheckoutButtonText: 'Checkout'
|
|
405
405
|
}
|
|
@@ -419,26 +419,13 @@ This allows the cart to survive:
|
|
|
419
419
|
- Browser restarts
|
|
420
420
|
- Navigation between pages
|
|
421
421
|
|
|
422
|
-
### Cross-Tab
|
|
423
|
-
|
|
424
|
-
When you update the cart in one tab, all other open tabs automatically sync:
|
|
425
|
-
|
|
426
|
-
```javascript
|
|
427
|
-
// Tab 1: Add item
|
|
428
|
-
await window.LiquidCommerce.elements.actions.cart.addProduct([...]);
|
|
429
|
-
|
|
430
|
-
// Tab 2: Cart automatically updates
|
|
431
|
-
// No additional code needed
|
|
432
|
-
```
|
|
422
|
+
### Cross-Tab Persistence
|
|
433
423
|
|
|
434
|
-
The SDK
|
|
435
|
-
- localStorage events
|
|
436
|
-
- Periodic polling
|
|
437
|
-
- API-based fallback
|
|
424
|
+
The cart is persisted to `localStorage` and reloaded on a fresh page load. The SDK does **not** provide live cross-tab synchronization — changes made in one tab will not automatically appear in other already-open tabs (there is no `storage` listener, `BroadcastChannel`, or polling). Another tab reflects the change only after it reloads.
|
|
438
425
|
|
|
439
426
|
### Session Duration
|
|
440
427
|
|
|
441
|
-
|
|
428
|
+
Cart and address session IDs are persisted in `localStorage` (with an API fallback) and are not automatically cleared by the SDK; cart lifetime/expiry is governed by server-side policy.
|
|
442
429
|
|
|
443
430
|
## Address Requirement
|
|
444
431
|
|
|
@@ -606,8 +593,9 @@ The `{token}` placeholder is replaced with the session checkout token.
|
|
|
606
593
|
```javascript
|
|
607
594
|
// Track cart events for analytics
|
|
608
595
|
window.addEventListener('lce:actions.cart_item_added', (event) => {
|
|
596
|
+
const { itemId, quantity } = event.detail.data;
|
|
609
597
|
gtag('event', 'add_to_cart', {
|
|
610
|
-
|
|
598
|
+
items: [{ item_id: itemId, quantity }],
|
|
611
599
|
currency: 'USD'
|
|
612
600
|
});
|
|
613
601
|
});
|
|
@@ -615,7 +603,7 @@ window.addEventListener('lce:actions.cart_item_added', (event) => {
|
|
|
615
603
|
window.addEventListener('lce:actions.cart_updated', (event) => {
|
|
616
604
|
// Update header cart count
|
|
617
605
|
document.getElementById('cart-badge').textContent =
|
|
618
|
-
event.detail.data.
|
|
606
|
+
event.detail.data.current.itemCount;
|
|
619
607
|
});
|
|
620
608
|
```
|
|
621
609
|
|
|
@@ -637,9 +625,9 @@ if (campaign === 'summer-sale') {
|
|
|
637
625
|
```javascript
|
|
638
626
|
// Store cart ID in your system
|
|
639
627
|
window.addEventListener('lce:actions.cart_updated', (event) => {
|
|
640
|
-
const { cartId,
|
|
628
|
+
const { cartId, itemCount } = event.detail.data.current;
|
|
641
629
|
|
|
642
|
-
if (
|
|
630
|
+
if (itemCount > 0) {
|
|
643
631
|
// Send cart ID to your backend for abandoned cart emails
|
|
644
632
|
fetch('/api/track-cart', {
|
|
645
633
|
method: 'POST',
|
|
@@ -695,9 +683,9 @@ Show appropriate messaging for empty carts:
|
|
|
695
683
|
|
|
696
684
|
```javascript
|
|
697
685
|
window.addEventListener('lce:actions.cart_updated', (event) => {
|
|
698
|
-
const {
|
|
686
|
+
const { itemCount } = event.detail.data.current;
|
|
699
687
|
|
|
700
|
-
if (
|
|
688
|
+
if (itemCount === 0) {
|
|
701
689
|
// Show empty state in your UI
|
|
702
690
|
document.getElementById('cart-status').textContent =
|
|
703
691
|
'Your cart is empty';
|
|
@@ -45,13 +45,12 @@ Configure checkout to load from URL parameter:
|
|
|
45
45
|
data-liquid-commerce-elements
|
|
46
46
|
data-token="YOUR_API_KEY"
|
|
47
47
|
data-env="production"
|
|
48
|
-
data-checkout-container="checkout"
|
|
49
48
|
data-checkout-param="lce_checkout"
|
|
50
49
|
type="text/javascript"
|
|
51
50
|
src="https://elements.reservebar-worker.workers.dev/all/elements.js"
|
|
52
51
|
></script>
|
|
53
52
|
|
|
54
|
-
<div
|
|
53
|
+
<div data-lce-checkout></div>
|
|
55
54
|
```
|
|
56
55
|
|
|
57
56
|
Visit `https://yoursite.com/checkout?lce_checkout=checkout_abc123` to load that checkout.
|
|
@@ -208,7 +207,7 @@ window.LiquidCommerce.elements.actions.checkout.updateCustomerInfo({
|
|
|
208
207
|
lastName: 'Doe',
|
|
209
208
|
email: 'john@example.com',
|
|
210
209
|
phone: '+15551234567',
|
|
211
|
-
birthDate: '
|
|
210
|
+
birthDate: '1990-01-15',
|
|
212
211
|
addressTwo: 'Apt 4',
|
|
213
212
|
company: 'Acme Corp'
|
|
214
213
|
});
|
|
@@ -274,7 +273,7 @@ console.log(checkoutData);
|
|
|
274
273
|
// {
|
|
275
274
|
// token: 'abc123xyz',
|
|
276
275
|
// cartId: 'cart_abc123',
|
|
277
|
-
// items:
|
|
276
|
+
// items: { 'cart_item_id': { ... } },
|
|
278
277
|
// amounts: {
|
|
279
278
|
// subtotal: 9998,
|
|
280
279
|
// tax: 800,
|
|
@@ -282,8 +281,6 @@ console.log(checkoutData);
|
|
|
282
281
|
// tip: 200,
|
|
283
282
|
// total: 11498
|
|
284
283
|
// },
|
|
285
|
-
// customer: { ... },
|
|
286
|
-
// shippingAddress: { ... },
|
|
287
284
|
// isGift: false,
|
|
288
285
|
// ...
|
|
289
286
|
// }
|
|
@@ -307,7 +304,7 @@ window.addEventListener('lce:actions.checkout_closed', (event) => {
|
|
|
307
304
|
});
|
|
308
305
|
|
|
309
306
|
window.addEventListener('lce:actions.checkout_failed', (event) => {
|
|
310
|
-
console.error('Checkout failed:', event.detail.data.
|
|
307
|
+
console.error('Checkout failed:', event.detail.data.message);
|
|
311
308
|
});
|
|
312
309
|
```
|
|
313
310
|
|
|
@@ -315,8 +312,8 @@ window.addEventListener('lce:actions.checkout_failed', (event) => {
|
|
|
315
312
|
|
|
316
313
|
```javascript
|
|
317
314
|
window.addEventListener('lce:actions.checkout_customer_information_updated', (event) => {
|
|
318
|
-
const {
|
|
319
|
-
console.log('Customer info updated:',
|
|
315
|
+
const { cartId } = event.detail.data;
|
|
316
|
+
console.log('Customer info updated for cart:', cartId);
|
|
320
317
|
});
|
|
321
318
|
```
|
|
322
319
|
|
|
@@ -324,8 +321,8 @@ window.addEventListener('lce:actions.checkout_customer_information_updated', (ev
|
|
|
324
321
|
|
|
325
322
|
```javascript
|
|
326
323
|
window.addEventListener('lce:actions.checkout_is_gift_toggled', (event) => {
|
|
327
|
-
const {
|
|
328
|
-
console.log('Gift mode:',
|
|
324
|
+
const { isActive } = event.detail.data;
|
|
325
|
+
console.log('Gift mode:', isActive ? 'enabled' : 'disabled');
|
|
329
326
|
});
|
|
330
327
|
|
|
331
328
|
window.addEventListener('lce:actions.checkout_gift_information_updated', (event) => {
|
|
@@ -337,8 +334,8 @@ window.addEventListener('lce:actions.checkout_gift_information_updated', (event)
|
|
|
337
334
|
|
|
338
335
|
```javascript
|
|
339
336
|
window.addEventListener('lce:actions.checkout_billing_same_as_shipping_toggled', (event) => {
|
|
340
|
-
const {
|
|
341
|
-
console.log('Billing same as shipping:',
|
|
337
|
+
const { isActive } = event.detail.data;
|
|
338
|
+
console.log('Billing same as shipping:', isActive);
|
|
342
339
|
});
|
|
343
340
|
|
|
344
341
|
window.addEventListener('lce:actions.checkout_billing_information_updated', (event) => {
|
|
@@ -350,8 +347,8 @@ window.addEventListener('lce:actions.checkout_billing_information_updated', (eve
|
|
|
350
347
|
|
|
351
348
|
```javascript
|
|
352
349
|
window.addEventListener('lce:actions.checkout_marketing_preferences_toggled', (event) => {
|
|
353
|
-
const {
|
|
354
|
-
console.log(`Marketing ${
|
|
350
|
+
const { fieldName, isActive } = event.detail.data;
|
|
351
|
+
console.log(`Marketing ${fieldName}:`, isActive);
|
|
355
352
|
});
|
|
356
353
|
```
|
|
357
354
|
|
|
@@ -359,18 +356,18 @@ window.addEventListener('lce:actions.checkout_marketing_preferences_toggled', (e
|
|
|
359
356
|
|
|
360
357
|
```javascript
|
|
361
358
|
window.addEventListener('lce:actions.checkout_item_removed', (event) => {
|
|
362
|
-
const {
|
|
363
|
-
console.log('Item removed:',
|
|
359
|
+
const { cartItemId } = event.detail.data;
|
|
360
|
+
console.log('Item removed:', cartItemId);
|
|
364
361
|
});
|
|
365
362
|
|
|
366
363
|
window.addEventListener('lce:actions.checkout_item_quantity_increase', (event) => {
|
|
367
|
-
const {
|
|
368
|
-
console.log(`Item ${
|
|
364
|
+
const { cartItemId, quantity } = event.detail.data;
|
|
365
|
+
console.log(`Item ${cartItemId} quantity: ${quantity}`);
|
|
369
366
|
});
|
|
370
367
|
|
|
371
368
|
window.addEventListener('lce:actions.checkout_item_quantity_decrease', (event) => {
|
|
372
|
-
const {
|
|
373
|
-
console.log(`Item ${
|
|
369
|
+
const { cartItemId, quantity } = event.detail.data;
|
|
370
|
+
console.log(`Item ${cartItemId} quantity: ${quantity}`);
|
|
374
371
|
});
|
|
375
372
|
```
|
|
376
373
|
|
|
@@ -378,8 +375,9 @@ window.addEventListener('lce:actions.checkout_item_quantity_decrease', (event) =
|
|
|
378
375
|
|
|
379
376
|
```javascript
|
|
380
377
|
window.addEventListener('lce:actions.checkout_tip_updated', (event) => {
|
|
381
|
-
const {
|
|
382
|
-
|
|
378
|
+
const { deliveryTips } = event.detail.data;
|
|
379
|
+
const total = deliveryTips.reduce((sum, t) => sum + t.tip, 0);
|
|
380
|
+
console.log('Tip amount:', total / 100);
|
|
383
381
|
});
|
|
384
382
|
```
|
|
385
383
|
|
|
@@ -392,14 +390,14 @@ window.addEventListener('lce:actions.checkout_submit_started', (event) => {
|
|
|
392
390
|
});
|
|
393
391
|
|
|
394
392
|
window.addEventListener('lce:actions.checkout_submit_completed', (event) => {
|
|
395
|
-
const {
|
|
396
|
-
console.log('Order completed:',
|
|
393
|
+
const { orderNumber } = event.detail.data;
|
|
394
|
+
console.log('Order completed:', orderNumber);
|
|
397
395
|
// Redirect to confirmation page
|
|
398
396
|
});
|
|
399
397
|
|
|
400
398
|
window.addEventListener('lce:actions.checkout_submit_failed', (event) => {
|
|
401
|
-
const {
|
|
402
|
-
console.error('Payment failed:',
|
|
399
|
+
const { message } = event.detail.data;
|
|
400
|
+
console.error('Payment failed:', message);
|
|
403
401
|
// Show error message
|
|
404
402
|
});
|
|
405
403
|
```
|
|
@@ -566,8 +564,8 @@ window.addEventListener('lce:actions.checkout_customer_information_updated', ()
|
|
|
566
564
|
|
|
567
565
|
window.addEventListener('lce:actions.checkout_submit_completed', (event) => {
|
|
568
566
|
gtag('event', 'purchase', {
|
|
569
|
-
transaction_id: event.detail.data.
|
|
570
|
-
value: event.detail.data.
|
|
567
|
+
transaction_id: event.detail.data.orderNumber,
|
|
568
|
+
value: event.detail.data.orderTotal / 100,
|
|
571
569
|
currency: 'USD'
|
|
572
570
|
});
|
|
573
571
|
});
|
package/docs/v1/guides/events.md
CHANGED
|
@@ -64,7 +64,7 @@ window.addEventListener('lce:actions.client_ready', (event) => {
|
|
|
64
64
|
|
|
65
65
|
Fires when a product component finishes loading and product data is available.
|
|
66
66
|
|
|
67
|
-
**Data includes:** `identifier`, `name`, `
|
|
67
|
+
**Data includes:** `identifier`, `name`, `priceInfo`, `selectedSizeId`, `selectedFulfillmentType`.
|
|
68
68
|
|
|
69
69
|
**Example**
|
|
70
70
|
|
|
@@ -819,7 +819,7 @@ window.addEventListener('lce:actions.checkout_gift_card_failed', (event) => {
|
|
|
819
819
|
|
|
820
820
|
Fires when products are added to checkout via the actions API.
|
|
821
821
|
|
|
822
|
-
**Data includes:** `cartId`, `itemsAdded`, `identifiers
|
|
822
|
+
**Data includes:** `cartId`, `itemsAdded`, `identifiers`.
|
|
823
823
|
|
|
824
824
|
**Example**
|
|
825
825
|
|
|
@@ -834,7 +834,7 @@ window.addEventListener('lce:actions.checkout_product_add_success', (event) => {
|
|
|
834
834
|
|
|
835
835
|
Fires when adding products to checkout via the actions API fails.
|
|
836
836
|
|
|
837
|
-
**Data includes:** `cartId`, `identifiers`, `error
|
|
837
|
+
**Data includes:** `cartId`, `identifiers`, `error`.
|
|
838
838
|
|
|
839
839
|
**Example**
|
|
840
840
|
|
|
@@ -904,7 +904,7 @@ window.addEventListener('lce:actions.product_loaded', (event) => {
|
|
|
904
904
|
items: [{
|
|
905
905
|
item_id: data.identifier,
|
|
906
906
|
item_name: data.name,
|
|
907
|
-
price: data.
|
|
907
|
+
price: data.priceInfo?.minimum / 100
|
|
908
908
|
}]
|
|
909
909
|
});
|
|
910
910
|
});
|