@liquidcommerce/elements-sdk 2.2.0-beta.3 → 2.2.0-beta.30

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.
Files changed (65) hide show
  1. package/README.md +1626 -571
  2. package/dist/index.esm.js +10292 -8153
  3. package/dist/types/core/auth.service.d.ts +10 -4
  4. package/dist/types/core/base-component.service.d.ts +3 -0
  5. package/dist/types/core/circuit-breaker.service.d.ts +54 -0
  6. package/dist/types/core/client/client-action.service.d.ts +15 -13
  7. package/dist/types/core/client/client-config.service.d.ts +5 -3
  8. package/dist/types/core/command/common-command.service.d.ts +2 -1
  9. package/dist/types/core/debug-panel/debug-panel.service.d.ts +43 -0
  10. package/dist/types/core/debug-panel/debug-panel.styles.d.ts +1 -0
  11. package/dist/types/core/fingerprint.service.d.ts +4 -9
  12. package/dist/types/core/google-tag-manager.service.d.ts +127 -2
  13. package/dist/types/core/logger/logger-factory.d.ts +3 -0
  14. package/dist/types/core/logger/logger.service.d.ts +8 -5
  15. package/dist/types/core/pubsub/interfaces/cart.interface.d.ts +1 -0
  16. package/dist/types/core/pubsub/interfaces/checkout.interface.d.ts +44 -6
  17. package/dist/types/core/pubsub/interfaces/core.interface.d.ts +2 -3
  18. package/dist/types/core/pubsub/interfaces/product.interface.d.ts +43 -6
  19. package/dist/types/core/store/interfaces/cart.interface.d.ts +1 -1
  20. package/dist/types/core/store/interfaces/checkout.interface.d.ts +0 -1
  21. package/dist/types/core/store/interfaces/core.interface.d.ts +2 -2
  22. package/dist/types/core/store/interfaces/product.interface.d.ts +18 -7
  23. package/dist/types/core/store/store.service.d.ts +1 -0
  24. package/dist/types/core/telemetry/telemetry.interface.d.ts +80 -0
  25. package/dist/types/core/telemetry/telemetry.service.d.ts +27 -0
  26. package/dist/types/enums/core.enum.d.ts +0 -1
  27. package/dist/types/enums/debug.enum.d.ts +6 -0
  28. package/dist/types/enums/index.d.ts +1 -0
  29. package/dist/types/interfaces/cloud/product.interface.d.ts +2 -0
  30. package/dist/types/interfaces/core.interface.d.ts +2 -2
  31. package/dist/types/modules/address/address.command.d.ts +1 -3
  32. package/dist/types/modules/cart/cart.commands.d.ts +1 -1
  33. package/dist/types/modules/cart/cart.component.d.ts +1 -2
  34. package/dist/types/modules/cart/components/cart-footer.component.d.ts +1 -0
  35. package/dist/types/modules/cart/components/cart-item.component.d.ts +2 -6
  36. package/dist/types/modules/checkout/checkout.commands.d.ts +3 -2
  37. package/dist/types/modules/checkout/checkout.component.d.ts +1 -2
  38. package/dist/types/modules/checkout/components/checkout-summary-section.component.d.ts +2 -0
  39. package/dist/types/modules/checkout/components/information/checkout-delivery-information-form.component.d.ts +1 -1
  40. package/dist/types/modules/checkout/components/summary/checkout-item-quantity.component.d.ts +0 -2
  41. package/dist/types/modules/checkout/components/summary/checkout-item.component.d.ts +2 -1
  42. package/dist/types/modules/checkout/components/summary/checkout-items.component.d.ts +1 -0
  43. package/dist/types/modules/checkout/components/summary/checkout-place-order-button.component.d.ts +0 -1
  44. package/dist/types/modules/checkout/constant.d.ts +0 -1
  45. package/dist/types/modules/product/components/index.d.ts +1 -0
  46. package/dist/types/modules/product/components/product-add-to-cart-section.component.d.ts +1 -0
  47. package/dist/types/modules/product/components/product-interactions.component.d.ts +4 -1
  48. package/dist/types/modules/product/components/product-price.component.d.ts +1 -0
  49. package/dist/types/modules/product/components/product-retailers.component.d.ts +1 -0
  50. package/dist/types/modules/product/product.commands.d.ts +1 -1
  51. package/dist/types/modules/ui-components/engraving/engraving-form.component.d.ts +13 -11
  52. package/dist/types/modules/ui-components/engraving/engraving-view.component.d.ts +4 -9
  53. package/dist/types/static/icon/index.d.ts +0 -1
  54. package/dist/types/utils/format.d.ts +2 -1
  55. package/docs/ACTIONS.md +1237 -0
  56. package/docs/BROWSER_SUPPORT.md +279 -0
  57. package/docs/CONFIGURATION.md +613 -0
  58. package/docs/DOCUMENTATION_INDEX.md +311 -0
  59. package/docs/EVENTS.md +765 -0
  60. package/docs/PROXY.md +228 -0
  61. package/docs/THEMING.md +592 -0
  62. package/docs/TROUBLESHOOTING.md +755 -0
  63. package/package.json +17 -17
  64. package/umd/elements.js +1 -1
  65. package/dist/types/static/icon/completed.icon.d.ts +0 -2
package/README.md CHANGED
@@ -28,48 +28,20 @@ Elements SDK
28
28
  <summary>Click to expand</summary>
29
29
 
30
30
  - [Overview](#-overview)
31
- - [Latest Features](#-latest-features)
32
- - [Key Features](#-key-features)
33
- - [Architecture](#-architecture)
34
- - [System Architecture](#system-architecture)
35
- - [Component Architecture](#component-architecture)
36
- - [Event Flow](#event-flow)
37
- - [Features](#-features)
38
- - [Installation](#-installation)
39
- - [CDN Usage](#option-a--use-the-cdn)
40
- - [NPM Installation](#option-b--install-from-npm)
41
- - [Browser Support](#-browser-support)
42
31
  - [Quick Start](#-quick-start)
43
- - [Auto-initialization](#step-1--auto-initialization-easiest)
44
- - [Product Mapping](#step-2--map-products-to-containers)
45
- - [Programmatic Control](#step-3--programmatic-control-advanced)
32
+ - [Advanced Usage](#-advanced-usage)
33
+ - [Browser Support](#-browser-support)
34
+ - [Configuration](#-configuration)
46
35
  - [SDK Methods & API](#-sdk-methods--api)
47
- - [Core Client Methods](#core-client-methods)
48
- - [UI Methods](#ui-methods)
49
- - [Builder Methods](#builder-methods-development-mode)
50
36
  - [Actions](#-actions)
51
- - [Product Actions](#product-actions)
52
- - [Address Actions](#address-actions)
53
- - [Cart Actions](#cart-actions)
54
- - [Checkout Actions](#checkout-actions)
55
37
  - [Events](#-events)
56
- - [Event Listening](#event-listening)
57
- - [Available Events](#available-events)
58
- - [Configuration](#-configuration)
59
- - [Module Options](#module-options)
60
- - [Environment Options](#environment-options)
61
- - [Auto-init Attributes](#auto-init-data-attributes)
62
38
  - [Themes & Customization](#-themes--customization)
63
- - [Theme Configuration](#theme-configuration)
64
- - [Dynamic Updates](#dynamic-theme-updates)
39
+ - [Features Deep Dive](#-features-deep-dive)
40
+ - [Core Capabilities](#-core-capabilities)
41
+ - [Integration Patterns](#-integration-patterns)
42
+ - [Error Handling](#-error-handling)
43
+ - [Performance & Best Practices](#-performance--best-practices)
65
44
  - [Proxy Configuration](#-proxy-configuration)
66
- - [Demo Pages](#-demo-pages)
67
- - [Simple Demo](#simple-demo-demosimplehtml)
68
- - [Advanced Demo](#advanced-demo-demoadvancedhtml)
69
- - [Development Scripts](#-development-scripts)
70
- - [Build Commands](#build-commands)
71
- - [Code Quality](#code-quality-commands)
72
- - [Maintenance](#maintenance-commands)
73
45
  - [Documentation](#-documentation)
74
46
  - [Versioning](#-versioning)
75
47
  - [Support](#-support)
@@ -80,14 +52,6 @@ Elements SDK
80
52
 
81
53
  The LiquidCommerce Elements SDK is a **production-ready JavaScript library** that enables partners to seamlessly integrate product displays, shopping carts, and checkout flows into any website. Built with performance and developer experience in mind.
82
54
 
83
- ### 🆕 Latest Features
84
-
85
- - **Builder Mode**: Dynamic theme customization for development environments
86
- - **Action Feedback Events**: All actions now emit success/failure events for better UX
87
- - **Proxy Support**: Route API requests through your server to avoid ad blockers
88
- - **Enhanced CLI**: Improved development scripts with parallel builds and better error handling
89
- - **TypeScript Support**: Full TypeScript definitions for better IDE experience
90
-
91
55
  ### ✨ Key Features
92
56
 
93
57
  <table>
@@ -133,399 +97,550 @@ The LiquidCommerce Elements SDK is a **production-ready JavaScript library** tha
133
97
  </tr>
134
98
  </table>
135
99
 
136
- ## 🏗️ Architecture
137
-
138
- ### System Architecture
139
-
140
- ```mermaid
141
- graph TB
142
- subgraph "Your Website"
143
- HTML[HTML Page]
144
- JS[JavaScript]
145
- INIT[Elements SDK]
146
- end
147
-
148
- subgraph "Elements SDK Core"
149
- CLIENT[Elements Client]
150
-
151
- subgraph "Components"
152
- PROD[Product Component]
153
- CART[Cart Component]
154
- CHECK[Checkout Component]
155
- ADDR[Address Component]
156
- end
157
-
158
- subgraph "Services"
159
- ACT[Actions Service]
160
- EVT[Events Service]
161
- API[API Client]
162
- THEME[Theme Provider]
163
- end
164
-
165
- subgraph "UI Layer"
166
- BTN[Cart Button]
167
- FLOAT[Floating Cart]
168
- DISP[Live Displays]
169
- end
170
- end
171
-
172
- subgraph "LiquidCommerce API"
173
- PAPI[Products API]
174
- CAPI[Cart API]
175
- OAPI[Orders API]
176
- AAPI[Address API]
177
- end
178
-
179
- HTML --> INIT
180
- JS --> CLIENT
181
-
182
- CLIENT --> PROD
183
- CLIENT --> CART
184
- CLIENT --> CHECK
185
- CLIENT --> ADDR
186
-
187
- PROD --> API
188
- CART --> API
189
- CHECK --> API
190
- ADDR --> API
191
-
192
- API --> PAPI
193
- API --> CAPI
194
- API --> OAPI
195
- API --> AAPI
196
-
197
- ACT --> EVT
198
- CLIENT --> ACT
199
- CLIENT --> THEME
200
- ```
201
-
202
- ### Component Architecture
203
-
204
- ```mermaid
205
- graph LR
206
- subgraph "Product Component"
207
- PD[Product Display]
208
- PS[Size Selector]
209
- PQ[Quantity Control]
210
- PA[Add to Cart]
211
- end
212
-
213
- subgraph "Cart Component"
214
- CI[Cart Items]
215
- CQ[Quantity Update]
216
- CP[Promo Code]
217
- CT[Cart Total]
218
- end
219
-
220
- subgraph "Checkout Component"
221
- CS[Shipping Info]
222
- CB[Billing Info]
223
- PM[Payment Method]
224
- OS[Order Summary]
225
- end
226
-
227
- PD --> PS
228
- PS --> PQ
229
- PQ --> PA
230
-
231
- CI --> CQ
232
- CQ --> CT
233
- CP --> CT
234
-
235
- CS --> CB
236
- CB --> PM
237
- PM --> OS
238
- ```
239
-
240
- ### Event Flow
241
-
242
- ```mermaid
243
- sequenceDiagram
244
- participant User
245
- participant SDK
246
- participant Actions
247
- participant Events
248
- participant API
249
- participant Website
250
-
251
- User->>SDK: Add to Cart
252
- SDK->>Actions: cart.addProduct()
253
- Actions->>API: POST /cart/items
254
- API-->>Actions: Response
255
- Actions->>Events: Emit Success/Failure
256
- Events->>Website: lce:actions.cart_product_add_success
257
- Website->>User: Show Feedback
258
- ```
259
-
260
- ## 🚀 Features
261
-
262
- - **🎯 Auto-initialization**: Single script tag with data attributes
263
- - **📦 Zero Dependencies**: Everything bundled, no peer dependencies
264
- - **🌐 CDN Ready**: No build step required for basic usage
265
- - **⚡ Lightweight**: ~150KB minified bundle size
266
- - **🔧 Framework Agnostic**: Works with React, Vue, Angular, or vanilla JS
267
- - **📱 Responsive**: Mobile-first design approach
268
- - **♿ Accessible**: WCAG 2.1 AA compliant components
269
- - **🎨 Themeable**: Comprehensive customization system
270
- - **🔐 Secure**: PCI compliant checkout flow
271
- - **📊 Analytics Ready**: Built-in event system for tracking
272
- - **🌍 Multi-environment**: Support for dev, staging, and production
273
- - **🧪 Well Tested**: Comprehensive test coverage
274
-
275
- ## 📦 Installation
276
-
277
- ### Choose how to include the SDK
278
-
279
- - **Use our CDN** (no build step required)
280
- - **Install from NPM** (for bundlers like Vite, Webpack, etc.)
281
-
282
- ### Option A — Use the CDN
283
-
284
- Include the script on your page. Use the production or beta URL:
100
+ ## 🚀 Quick Start
285
101
 
286
- ```html
287
- <!-- Production (latest) -->
288
- <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
102
+ The fastest way to add e-commerce to your site is with **auto-initialization** - a single script tag that does everything.
289
103
 
290
- <!-- Beta (latest) -->
291
- <script src="https://assets-elements.liquidcommerce.us/all/beta/elements.js"></script>
292
- ```
104
+ ### The Simplest Setup (30 seconds)
293
105
 
294
- You can also pin to a specific version:
106
+ Add this single script tag to your page:
295
107
 
296
108
  ```html
297
- <script src="https://assets-elements.liquidcommerce.us/all/1.2.3/elements.js"></script>
109
+ <script
110
+ data-liquid-commerce-elements
111
+ data-token="YOUR_API_KEY"
112
+ data-env="production"
113
+ src="https://assets-elements.liquidcommerce.us/all/elements.js"
114
+ ></script>
298
115
  ```
299
116
 
300
- ### Option B Install from NPM
117
+ That's it! You now have:
118
+ - ✅ A floating cart button (bottom right)
119
+ - ✅ Full cart functionality
120
+ - ✅ Complete checkout flow
121
+ - ✅ Ready to add products
301
122
 
302
- ```bash
303
- npm install @liquidcommerceteam/elements-sdk
304
- # or
305
- pnpm add @liquidcommerceteam/elements-sdk
123
+ ### Adding Products to Your Page
124
+
125
+ Now let's display products. Choose the method that fits your use case:
126
+
127
+ #### Method 1: Direct Attributes (Best for static pages)
128
+
129
+ Add products directly in the script tag:
130
+
131
+ ```html
132
+ <div id="product-1"></div>
133
+ <div id="product-2"></div>
134
+
135
+ <script
136
+ data-liquid-commerce-elements
137
+ data-token="YOUR_API_KEY"
138
+ data-env="production"
139
+ data-container-1="product-1"
140
+ data-product-1="00619947000020"
141
+ data-container-2="product-2"
142
+ data-product-2="00832889005513"
143
+ src="https://assets-elements.liquidcommerce.us/all/elements.js"
144
+ ></script>
306
145
  ```
307
146
 
308
- Then import and initialize in your app code:
147
+ **Use case:** Static HTML pages with known products
309
148
 
310
- ```js
311
- import { Elements } from '@liquidcommerceteam/elements-sdk';
149
+ #### Method 2: JSON Configuration (Best for CMS/dynamic content)
312
150
 
313
- const client = await Elements('YOUR_API_KEY', {
314
- env: 'production',
315
- });
151
+ Configure products via a JSON script block:
152
+
153
+ ```html
154
+ <div id="product-1"></div>
155
+ <div id="product-2"></div>
156
+
157
+ <script data-liquid-commerce-elements-products type="application/json">
158
+ [
159
+ { "containerId": "product-1", "identifier": "00619947000020" },
160
+ { "containerId": "product-2", "identifier": "00832889005513" }
161
+ ]
162
+ </script>
163
+
164
+ <script
165
+ data-liquid-commerce-elements
166
+ data-token="YOUR_API_KEY"
167
+ data-env="production"
168
+ src="https://assets-elements.liquidcommerce.us/all/elements.js"
169
+ ></script>
316
170
  ```
317
171
 
318
- ## 🌐 Browser Support
172
+ **Use case:** CMS platforms, templating engines, server-side rendering
319
173
 
320
- ⚠️ **Important**: This SDK is designed for browser environments only. It will not work in server-side rendering, Node.js, or other non-browser environments. The SDK includes built-in safety measures to prevent errors when accidentally imported in these environments.
174
+ #### Method 3: Annotated Elements (Best for grids/lists)
321
175
 
322
- ### Supported Browsers
176
+ Mark any div with a data attribute:
323
177
 
324
- The SDK supports **2018+ browsers** with comprehensive polyfills:
178
+ ```html
179
+ <div class="product-grid">
180
+ <div data-lce-product="00619947000020"></div>
181
+ <div data-lce-product="00832889005513"></div>
182
+ <div data-lce-product="00851468007252"></div>
183
+ </div>
325
184
 
326
- | Browser | Minimum Version | Released |
327
- |---------|----------------|----------|
328
- | Chrome | 66+ | April 2018 |
329
- | Firefox | 60+ | May 2018 |
330
- | Safari | 12+ | September 2018 |
331
- | Edge | 79+ (Chromium) | January 2020 |
332
- | Samsung Internet | 7.2+ | June 2018 |
185
+ <script
186
+ data-liquid-commerce-elements
187
+ data-token="YOUR_API_KEY"
188
+ data-env="production"
189
+ src="https://assets-elements.liquidcommerce.us/all/elements.js"
190
+ ></script>
191
+ ```
333
192
 
334
- 📖 See [`docs/BROWSER_SUPPORT.md`](docs/BROWSER_SUPPORT.md) for detailed version compatibility and polyfill information.
193
+ **Use case:** Product grids, category pages, search results
335
194
 
336
- ## 🚀 Quick Start
195
+ ### Customizing the Cart Button
337
196
 
338
- ### Step 1 Auto-initialization (Easiest)
197
+ By default, you get a floating cart button. Here's how to customize it:
339
198
 
340
- This single script both loads the SDK and initializes it automatically. Place it:
341
- - At the end of the `<body>` (recommended), or
342
- - In the `<head>` with `defer` so it doesn't block rendering.
199
+ #### Option 1: Cart Button in a Specific Container
343
200
 
344
201
  ```html
345
- <!-- Body footer (recommended) -->
202
+ <nav>
203
+ <div id="header-cart"></div>
204
+ </nav>
205
+
346
206
  <script
347
207
  data-liquid-commerce-elements
348
208
  data-token="YOUR_API_KEY"
349
209
  data-env="production"
350
- data-cart-id="buttons-container"
210
+ data-cart-id="header-cart"
351
211
  data-show-cart-items
352
212
  src="https://assets-elements.liquidcommerce.us/all/elements.js"
353
213
  ></script>
214
+ ```
215
+
216
+ #### Option 2: No Cart Button (Manual Control)
354
217
 
355
- <!-- OR: Head with defer -->
218
+ ```html
356
219
  <script
357
- defer
358
220
  data-liquid-commerce-elements
359
221
  data-token="YOUR_API_KEY"
360
222
  data-env="production"
361
- data-cart-id="buttons-container"
362
- data-show-cart-items
223
+ data-hide-cart-floating-button
363
224
  src="https://assets-elements.liquidcommerce.us/all/elements.js"
364
225
  ></script>
365
226
  ```
366
227
 
367
- **Available data attributes:**
368
- - `data-token="YOUR_API_KEY"` - Your API key (required)
369
- - `data-env="production|development"` - Environment (default: production)
370
- - `data-cart-id="container-id"` - ID for cart button container (optional, creates floating button if omitted)
371
- - `data-show-cart-items` - Show items count badge on cart button (optional)
372
- - `data-enable-debugging` - Enable debug logging in development (optional)
228
+ ### Advanced Auto-Init Features
373
229
 
374
- Add containers where you want elements to render:
230
+ #### Add Product via URL (Marketing Links)
231
+
232
+ Enable "add to cart" via URL parameters for email campaigns and ads:
375
233
 
376
234
  ```html
377
- <div id="buttons-container"></div>
378
- <div id="pdp-1"></div>
379
- <div id="pdp-2"></div>
235
+ <script
236
+ data-liquid-commerce-elements
237
+ data-token="YOUR_API_KEY"
238
+ data-env="production"
239
+ data-product-param="lce_product"
240
+ data-product-fulfillment-type-param="lce_fulfillment"
241
+ src="https://assets-elements.liquidcommerce.us/all/elements.js"
242
+ ></script>
243
+ ```
244
+
245
+ Now this URL auto-adds a product to cart:
246
+ ```
247
+ https://yoursite.com/shop?lce_product=00619947000020&lce_fulfillment=shipping
380
248
  ```
381
249
 
382
- ### Step 2 Map products to containers
250
+ **Use case:** Email campaigns, social media ads, QR codes
383
251
 
384
- Choose one or combine multiple methods:
252
+ #### Apply Promo Code via URL (Campaign Tracking)
385
253
 
386
- #### 1) Attribute pairs on the main script
254
+ Auto-apply promo codes from URL parameters:
387
255
 
388
256
  ```html
389
257
  <script
390
258
  data-liquid-commerce-elements
391
259
  data-token="YOUR_API_KEY"
392
260
  data-env="production"
393
- data-container-1="pdp-1"
394
- data-product-1="00619947000020"
395
- data-container-2="pdp-2"
396
- data-product-2="00832889005513"
261
+ data-promo-code-param="lce_promo"
397
262
  src="https://assets-elements.liquidcommerce.us/all/elements.js"
398
263
  ></script>
399
264
  ```
400
265
 
401
- #### 2) JSON configuration script
266
+ Now this URL auto-applies a promo code:
267
+ ```
268
+ https://yoursite.com/shop?lce_promo=SUMMER20
269
+ ```
270
+
271
+ **Use case:** Promotional campaigns, influencer codes, affiliate links
272
+
273
+ #### Promo Ticker (Rotating Promotions)
274
+
275
+ Display rotating promotional messages:
402
276
 
403
277
  ```html
404
- <script data-liquid-commerce-elements-products type="application/json">
405
- [
406
- { "containerId": "pdp-1", "identifier": "00619947000020" },
407
- { "containerId": "pdp-2", "identifier": "00832889005513" }
408
- ]
409
- </script>
278
+ <script
279
+ data-liquid-commerce-elements
280
+ data-token="YOUR_API_KEY"
281
+ data-env="production"
282
+ data-promo-code="FREESHIP"
283
+ data-promo-text="Free Shipping Today Only!|Use code FREESHIP at checkout"
284
+ data-promo-separator="•"
285
+ data-promo-active-from="2025-01-01T00:00:00Z"
286
+ data-promo-active-until="2025-01-31T23:59:59Z"
287
+ src="https://assets-elements.liquidcommerce.us/all/elements.js"
288
+ ></script>
410
289
  ```
411
290
 
412
- #### 3) Annotated elements
291
+ **Use case:** Time-sensitive promotions, holiday sales, flash deals
292
+
293
+ #### Debug Mode (Development)
294
+
295
+ Enable debug logging during development:
413
296
 
414
297
  ```html
415
- <div data-lce-product="00619947000020"></div>
416
- <div data-lce-product="00832889005513"></div>
298
+ <script
299
+ data-liquid-commerce-elements
300
+ data-token="YOUR_API_KEY"
301
+ data-env="development"
302
+ data-debug-mode="console"
303
+ src="https://assets-elements.liquidcommerce.us/all/elements.js"
304
+ ></script>
305
+ ```
306
+
307
+ **Debug modes:**
308
+ - `console` - Logs to browser console
309
+ - `panel` - Shows visual debug panel + console logs
310
+ - Not set - No debugging (production default)
311
+
312
+ ### Complete Auto-Init Reference
313
+
314
+ Here's every available data attribute:
315
+
316
+ ```html
317
+ <script
318
+ data-liquid-commerce-elements
319
+
320
+ <!-- Required -->
321
+ data-token="YOUR_API_KEY"
322
+
323
+ <!-- Environment -->
324
+ data-env="production|staging|development|local"
325
+
326
+ <!-- Cart Button -->
327
+ data-cart-id="container-id"
328
+ data-show-cart-items
329
+ data-hide-cart-floating-button
330
+
331
+ <!-- Products (Method 1: Direct) -->
332
+ data-container-1="div-id"
333
+ data-product-1="identifier"
334
+ data-container-2="div-id"
335
+ data-product-2="identifier"
336
+
337
+ <!-- URL Parameters -->
338
+ data-product-param="lce_product"
339
+ data-product-fulfillment-type-param="lce_fulfillment"
340
+ data-promo-code-param="lce_promo"
341
+
342
+ <!-- Promo Ticker -->
343
+ data-promo-code="CODE"
344
+ data-promo-text="Message 1|Message 2"
345
+ data-promo-separator="•"
346
+ data-promo-active-from="2025-01-01T00:00:00Z"
347
+ data-promo-active-until="2025-12-31T23:59:59Z"
348
+
349
+ <!-- Debugging (dev only) -->
350
+ data-debug-mode="console|panel"
351
+
352
+ src="https://assets-elements.liquidcommerce.us/all/elements.js"
353
+ ></script>
417
354
  ```
418
355
 
419
- ### Step 3 Programmatic Control (Advanced)
356
+ **📖 For complete auto-init options:** See [`docs/CONFIGURATION.md`](docs/CONFIGURATION.md) for all data attributes and configuration details.
420
357
 
421
- Initialize the SDK yourself for full control:
358
+ ---
359
+
360
+ ## 🔧 Advanced Usage
361
+
362
+ Need more control? Initialize programmatically for full access to the SDK API.
363
+
364
+ ### Installation
365
+
366
+ **CDN:**
367
+ ```html
368
+ <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
369
+
370
+ <!-- Pin to specific version: -->
371
+ <script src="https://assets-elements.liquidcommerce.us/all/1.2.3/elements.js"></script>
372
+ ```
373
+
374
+ **NPM:**
375
+ ```bash
376
+ npm install @liquidcommerce/elements-sdk
377
+ # or
378
+ pnpm add @liquidcommerce/elements-sdk
379
+ ```
380
+
381
+ ### Programmatic Initialization
422
382
 
423
383
  ```html
424
384
  <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
425
385
  <script>
426
- (async () => {
427
- const client = await window.Elements('YOUR_API_KEY', {
428
- env: 'production',
429
- enableDebugging: false, // only for development
430
- customTheme: { /* optional theming overrides */ }
431
- });
386
+ (async () => {
387
+ const client = await window.Elements('YOUR_API_KEY', {
388
+ env: 'production',
389
+ debugMode: 'none',
390
+ customTheme: { /* theming overrides */ },
391
+ proxy: { /* proxy config */ }
392
+ });
432
393
 
433
- // Your implementation here...
434
- })();
394
+ // Inject components
395
+ await client.injectProductElement([
396
+ { containerId: 'pdp-1', identifier: '00619947000020' }
397
+ ]);
398
+
399
+ // Create cart button
400
+ client.ui.cartButton('cart-container', true);
401
+
402
+ // Use actions API
403
+ await client.actions.cart.addProduct([{
404
+ identifier: '00619947000020',
405
+ fulfillmentType: 'shipping',
406
+ quantity: 1
407
+ }]);
408
+ })();
435
409
  </script>
436
410
  ```
437
411
 
438
- ## 📖 SDK Methods & API
412
+ **NPM Import:**
413
+ ```js
414
+ import { Elements } from '@liquidcommerce/elements-sdk';
415
+
416
+ const client = await Elements('YOUR_API_KEY', { env: 'production' });
417
+ ```
418
+
419
+ ---
420
+
421
+ ## 🌐 Browser Support
422
+
423
+ ⚠️ **Important**: This SDK is designed for browser environments only. It will not work in server-side rendering, Node.js, or other non-browser environments.
439
424
 
440
- ### Core Client Methods
425
+ ### Supported Browsers (2018+)
441
426
 
442
- Once initialized, the client provides these core methods:
427
+ | Browser | Minimum Version | Released |
428
+ |---------|----------------|----------|
429
+ | Chrome | 66+ | April 2018 |
430
+ | Firefox | 60+ | May 2018 |
431
+ | Safari | 12+ | September 2018 |
432
+ | Edge | 79+ (Chromium) | January 2020 |
433
+ | Samsung Internet | 7.2+ | June 2018 |
443
434
 
444
- #### Product Injection
435
+ 📖 See [`docs/BROWSER_SUPPORT.md`](docs/BROWSER_SUPPORT.md) for detailed compatibility.
445
436
 
446
- **`injectProductElement(params: IInjectProductElement[]): Promise<void>`**
437
+ ## ⚙️ Configuration
447
438
 
448
- Inject product components into containers:
439
+ ### Basic Configuration
449
440
 
450
441
  ```js
451
- await client.injectProductElement([
452
- { containerId: 'pdp-1', identifier: '00619947000020' },
453
- { containerId: 'pdp-2', identifier: '00832889005513' }
454
- ]);
442
+ const client = await Elements('YOUR_API_KEY', {
443
+ env: 'production', // Environment
444
+ debugMode: 'none', // Debug mode
445
+ customTheme: { }, // Theme overrides
446
+ proxy: { }, // Proxy configuration
447
+ promoTicker: [ ] // Promotional messages
448
+ });
455
449
  ```
456
450
 
457
- #### Cart Injection
451
+ ### Environment Options
458
452
 
459
- **`injectCartElement(containerId: string): Promise<void>`**
453
+ ```js
454
+ env: 'production' // Live environment (default)
455
+ env: 'staging' // Pre-production testing
456
+ env: 'development' // Development with extra logging
457
+ env: 'local' // Local development
458
+ ```
460
459
 
461
- Inject a cart component:
460
+ ### Debug Modes
462
461
 
463
462
  ```js
464
- await client.injectCartElement('cart-container');
463
+ debugMode: 'none' // No debugging (production default)
464
+ debugMode: 'console' // Console logs only
465
+ debugMode: 'panel' // Visual debug panel + console logs
465
466
  ```
466
467
 
467
- #### Checkout Injection
468
+ **Note:** Debug mode is automatically disabled in production environment for security.
468
469
 
469
- **`injectCheckoutElement(containerId: string): Promise<void>`**
470
+ ### Custom Theme
470
471
 
471
- Inject a checkout component:
472
+ Override default styles and layouts:
472
473
 
473
474
  ```js
474
- await client.injectCheckoutElement('checkout-container');
475
+ customTheme: {
476
+ global: {
477
+ theme: {
478
+ primaryColor: '#007bff',
479
+ accentColor: '#6c757d',
480
+ successColor: '#28a745',
481
+ errorColor: '#dc3545',
482
+ buttonCornerRadius: '8px',
483
+ cardCornerRadius: '12px',
484
+ headingFont: {
485
+ name: 'Inter',
486
+ weights: [600, 700]
487
+ },
488
+ paragraphFont: {
489
+ name: 'Inter',
490
+ weights: [400, 500]
491
+ }
492
+ },
493
+ layout: {
494
+ allowPromoCodes: true,
495
+ inputFieldStyle: 'outlined'
496
+ }
497
+ },
498
+ product: {
499
+ layout: {
500
+ showDescription: true,
501
+ addToCartButtonText: 'Add to Cart',
502
+ fulfillmentDisplay: 'carousel'
503
+ }
504
+ },
505
+ cart: {
506
+ layout: {
507
+ showQuantityCounter: true,
508
+ drawerHeaderText: 'Your Cart'
509
+ }
510
+ },
511
+ checkout: {
512
+ layout: {
513
+ allowGiftCards: true,
514
+ emailOptIn: { show: true, checked: false, text: 'Email me with news' },
515
+ smsOptIn: { show: true, checked: false, text: 'Text me with updates' }
516
+ }
517
+ }
518
+ }
475
519
  ```
476
520
 
477
- #### Address Injection
521
+ **📖 For complete theming options:** See [`docs/THEMING.md`](docs/THEMING.md)
478
522
 
479
- **`injectAddressElement(containerId: string): Promise<void>`**
523
+ ### Proxy Configuration
480
524
 
481
- Inject an address form component:
525
+ Route API requests through your server to avoid ad blockers:
482
526
 
483
527
  ```js
484
- await client.injectAddressElement('address-container');
528
+ proxy: {
529
+ baseUrl: 'https://yourdomain.com/api/proxy',
530
+ headers: {
531
+ 'X-Custom-Auth': 'your-token'
532
+ }
533
+ }
534
+ ```
535
+
536
+ See [`docs/PROXY.md`](docs/PROXY.md) for implementation guide.
537
+
538
+ ### Promo Ticker
539
+
540
+ Display rotating promotional messages:
541
+
542
+ ```js
543
+ promoTicker: [
544
+ {
545
+ promoCode: 'FREESHIP',
546
+ text: ['Free Shipping Today!', 'Use code FREESHIP'],
547
+ separator: '•',
548
+ activeFrom: '2025-01-01T00:00:00Z',
549
+ activeUntil: '2025-12-31T23:59:59Z'
550
+ }
551
+ ]
485
552
  ```
486
553
 
487
- ### UI Methods
554
+ **📖 For all configuration options:** See [`docs/CONFIGURATION.md`](docs/CONFIGURATION.md) for complete reference with TypeScript types.
555
+
556
+ ---
557
+
558
+ ## 📖 SDK Methods & API
559
+
560
+ ### Component Injection
488
561
 
489
- #### Cart Buttons
562
+ Inject SDK components into your page containers.
563
+
564
+ #### Products
565
+
566
+ ```js
567
+ await client.injectProductElement([
568
+ { containerId: 'pdp-1', identifier: '00619947000020' },
569
+ { containerId: 'pdp-2', identifier: '00832889005513' }
570
+ ]);
571
+ ```
490
572
 
491
- **`ui.cartButton(containerId: string, showItemsCount?: boolean): void`**
573
+ **Identifier types:** UPC, product ID, or Salsify grouping ID
492
574
 
493
- Create an "open cart" button in a specific container:
575
+ #### Cart
494
576
 
495
577
  ```js
496
- client.ui.cartButton('buttons-container');
578
+ await client.injectCartElement('cart-container');
579
+ ```
580
+
581
+ **Use case:** Dedicated cart page
582
+
583
+ #### Checkout
497
584
 
498
- // With items count badge
499
- client.ui.cartButton('buttons-container', true);
585
+ ```js
586
+ await client.injectCheckoutElement('checkout-container');
500
587
  ```
501
588
 
502
- **`ui.floatingCartButton(showItemsCount?: boolean): void`**
589
+ **Use case:** Dedicated checkout page
503
590
 
504
- Automatically inject a floating cart button:
591
+ #### Address
505
592
 
506
593
  ```js
507
- client.ui.floatingCartButton();
594
+ await client.injectAddressElement('address-container');
595
+ ```
508
596
 
509
- // With items count badge
510
- client.ui.floatingCartButton(true);
597
+ **Use case:** Shipping address collection page
598
+
599
+ ### UI Helpers
600
+
601
+ Create standalone UI elements that integrate with the SDK.
602
+
603
+ #### Cart Button (in container)
604
+
605
+ ```js
606
+ client.ui.cartButton('header-cart', true);
511
607
  ```
512
608
 
513
- #### Live Cart Display
609
+ **Parameters:**
610
+ - `containerId` - Where to place the button
611
+ - `showItemsCount` - Show item count badge (optional)
514
612
 
515
- **`ui.cartTotal(elementId: string): void`**
613
+ **Use case:** Header navigation, sidebar
516
614
 
517
- Bind an element to display the live cart total (automatically updates when cart changes):
615
+ #### Floating Cart Button
518
616
 
519
617
  ```js
520
- client.ui.cartTotal('cart-total-display');
618
+ client.ui.floatingCartButton(true);
521
619
  ```
522
620
 
523
- **`ui.cartItemsCount(elementId: string): void`**
621
+ **Parameters:**
622
+ - `showItemsCount` - Show item count badge (optional)
623
+
624
+ **Use case:** Always-visible cart access (bottom-right corner)
524
625
 
525
- Bind an element to display the live cart items count (automatically updates when cart changes):
626
+ #### Live Cart Data Display
627
+
628
+ Bind elements to auto-update with cart data:
526
629
 
527
630
  ```js
528
- client.ui.cartItemsCount('cart-items-badge');
631
+ // Show live subtotal
632
+ client.ui.cartSubtotal('cart-total-display');
633
+
634
+ // Show live item count
635
+ client.ui.cartItemsCount('cart-badge');
636
+ ```
637
+
638
+ **Example:**
639
+ ```html
640
+ <nav>
641
+ <span>Cart: $<span id="cart-total-display">0.00</span></span>
642
+ <span>(<span id="cart-badge">0</span> items)</span>
643
+ </nav>
529
644
  ```
530
645
 
531
646
  ### Builder Methods (Development Mode)
@@ -568,7 +683,8 @@ const actions = window.elements.actions;
568
683
  ```js
569
684
  // Get product details
570
685
  const product = actions.product.getDetails('product-123');
571
- console.log(product.productName, product.price, product.isAvailable);
686
+ console.log(product.name, product.brand, product.region, product.variety);
687
+ console.log(product.priceInfo, product.description, product.tastingNotes);
572
688
  ```
573
689
 
574
690
  ### Address Actions
@@ -669,7 +785,7 @@ await actions.cart.removePromoCode();
669
785
 
670
786
  // Get cart details
671
787
  const cart = actions.cart.getDetails();
672
- console.log(cart.total, cart.items.length);
788
+ console.log(cart.itemCount, cart.amounts.total, cart.amounts.giftCardTotal);
673
789
 
674
790
  // Reset cart
675
791
  await actions.cart.resetCart();
@@ -741,12 +857,10 @@ window.addEventListener('lce:actions.checkout_gift_card_failed', function(event)
741
857
 
742
858
  // Get checkout details (safe, non-sensitive data only)
743
859
  const checkout = actions.checkout.getDetails();
744
- console.log('Total:', checkout.amounts.total);
745
- console.log('Items:', checkout.itemCount);
746
- console.log('Is gift:', checkout.isGift);
747
- console.log('Has age verification:', checkout.hasAgeVerify);
748
- console.log('Has promo code:', checkout.hasPromoCode);
749
- console.log('Has gift cards:', checkout.hasGiftCards);
860
+ console.log(checkout.itemCount, checkout.amounts.total, checkout.isGift);
861
+ console.log(checkout.hasAgeVerify, checkout.hasPromoCode, checkout.hasGiftCards);
862
+ console.log(checkout.acceptedAccountCreation, checkout.billingSameAsShipping);
863
+ console.log(checkout.marketingPreferences);
750
864
 
751
865
  // Configure checkout options
752
866
  await actions.checkout.toggleBillingSameAsShipping(true);
@@ -762,13 +876,14 @@ The SDK emits real-time events for all user interactions. Listen to these events
762
876
  ```js
763
877
  // Listen for specific events
764
878
  window.addEventListener('lce:actions.product_add_to_cart', function(event) {
765
- const product = event.detail.data;
766
- console.log('Added to cart:', product.productName);
879
+ const data = event.detail.data;
880
+ console.log('Added to cart:', data.identifier);
767
881
 
768
882
  // Your custom logic here
769
883
  analytics.track('Product Added', {
770
- product: product.productName,
771
- price: product.price
884
+ identifier: data.identifier,
885
+ quantity: data.quantity,
886
+ upc: data.upc
772
887
  });
773
888
  });
774
889
 
@@ -785,7 +900,7 @@ window.elements.onAllActions((data, metadata) => {
785
900
  ### Available Events
786
901
 
787
902
  #### Product Events
788
- - `lce:actions.product_loaded` - Product component loaded
903
+ - `lce:actions.product_loaded` - Product component loaded with comprehensive product details (region, country, abv, proof, age, variety, vintage, descriptions, tasting notes)
789
904
  - `lce:actions.product_add_to_cart` - Item added to cart
790
905
  - `lce:actions.product_quantity_increase` - Quantity increased
791
906
  - `lce:actions.product_quantity_decrease` - Quantity decreased
@@ -793,6 +908,7 @@ window.elements.onAllActions((data, metadata) => {
793
908
  - `lce:actions.product_fulfillment_type_changed` - Delivery method changed
794
909
 
795
910
  #### Cart Events
911
+ - `lce:actions.cart_loaded` - Cart data loaded with complete cart information (itemCount, all amounts including giftCardTotal, detailed item data)
796
912
  - `lce:actions.cart_opened` - Cart displayed
797
913
  - `lce:actions.cart_closed` - Cart hidden
798
914
  - `lce:actions.cart_updated` - Cart contents changed
@@ -801,6 +917,7 @@ window.elements.onAllActions((data, metadata) => {
801
917
  - `lce:actions.cart_reset` - Cart cleared
802
918
 
803
919
  #### Checkout Events
920
+ - `lce:actions.checkout_loaded` - Checkout data loaded with comprehensive details (acceptedAccountCreation, hasSubstitutionPolicy, billingSameAsShipping, marketing preferences, detailed items)
804
921
  - `lce:actions.checkout_opened` - Checkout started
805
922
  - `lce:actions.checkout_closed` - Checkout abandoned
806
923
  - `lce:actions.checkout_submit_started` - Order submission began
@@ -813,361 +930,1299 @@ window.elements.onAllActions((data, metadata) => {
813
930
  - `lce:actions.address_updated` - Address information changed
814
931
  - `lce:actions.address_cleared` - Address removed
815
932
 
816
- See [`docs/EVENTS.md`](docs/EVENTS.md) for complete event reference with implementation examples.
817
-
818
- ## ⚙️ Configuration
819
-
820
- Configure the SDK when initializing:
821
-
822
- ```js
823
- const client = await Elements('YOUR_API_KEY', {
824
- env: 'production', // 'local' | 'development' | 'staging' | 'production'
825
- enableDebugging: false, // Enable console logging (development only)
826
- isBuilder: false, // Enable builder methods (development only)
827
- customTheme: { /* theme overrides */ },
828
- proxy: { /* proxy configuration */ }
829
- });
830
- ```
831
-
832
- ### Environment Options
833
-
834
- - **`production`**: Live environment for customer-facing sites
835
- - **`staging`**: Pre-production testing environment
836
- - **`development`**: Development environment with additional debugging
837
- - **`local`**: Local development environment
838
-
839
- ### Auto-init Data Attributes
840
-
841
- When using auto-initialization, configure via data attributes:
842
-
843
- - `data-liquid-commerce-elements`: Required flag to enable auto-init
844
- - `data-token`: Your API key (required)
845
- - `data-env`: Environment (defaults to production)
846
- - `data-cart-id`: Container ID for cart button
847
- - `data-enable-debugging`: Enable debugging mode
848
- - `data-container-X` / `data-product-X`: Product mapping pairs
933
+ See [`docs/EVENTS.md`](docs/EVENTS.md) for complete event reference with all available fields and implementation examples.
849
934
 
850
935
  ## 🎨 Themes & Customization
851
936
 
852
- Customize the appearance of SDK components using the theme system:
937
+ The SDK provides a theming system that lets you match components to your brand.
938
+
939
+ ### Global Theming
853
940
 
854
941
  ```js
855
942
  const client = await Elements('YOUR_API_KEY', {
856
- env: 'production',
857
943
  customTheme: {
858
944
  global: {
859
- colors: {
860
- primary: '#007bff',
861
- secondary: '#6c757d'
862
- },
863
- typography: {
864
- fontFamily: 'Roboto, sans-serif',
865
- fontSize: '16px'
866
- }
867
- },
868
- product: {
869
- layout: {
870
- imagePosition: 'left',
871
- showDescription: true
945
+ theme: {
946
+ primaryColor: '#007bff',
947
+ accentColor: '#6c757d',
948
+ successColor: '#28a745',
949
+ errorColor: '#dc3545',
950
+ warningColor: '#ffc107',
951
+ defaultTextColor: '#212529',
952
+ selectedTextColor: '#ffffff',
953
+ drawerBackgroundColor: '#ffffff',
954
+ buttonCornerRadius: '8px',
955
+ cardCornerRadius: '12px',
956
+ headingFont: {
957
+ name: 'Inter',
958
+ weights: [600, 700]
959
+ },
960
+ paragraphFont: {
961
+ name: 'Inter',
962
+ weights: [400, 500]
963
+ }
872
964
  },
873
- colors: {
874
- price: '#28a745',
875
- sale: '#dc3545'
876
- }
877
- },
878
- cart: {
879
- layout: {
880
- showRetailerLogos: true,
881
- compactMode: false
882
- }
883
- },
884
- checkout: {
885
965
  layout: {
886
- singlePage: true,
887
- showOrderSummary: true
966
+ enablePersonalization: true,
967
+ personalizationText: 'Customize your product',
968
+ personalizationCardStyle: 'outlined',
969
+ allowPromoCodes: true,
970
+ inputFieldStyle: 'outlined',
971
+ poweredByMode: 'light'
888
972
  }
889
973
  }
890
974
  }
891
975
  });
892
976
  ```
893
977
 
894
- In builder mode, themes can be updated dynamically:
978
+ ### Component-Specific Theming
979
+
980
+ #### Product Component
895
981
 
896
982
  ```js
897
- // Update themes in real-time (builder mode only)
898
- await client.builder.updateComponentGlobalConfigs({
899
- colors: { primary: '#ff6b6b' }
983
+ customTheme: {
984
+ product: {
985
+ theme: {
986
+ backgroundColor: '#ffffff'
987
+ },
988
+ layout: {
989
+ showImages: true,
990
+ showTitle: true,
991
+ showDescription: true,
992
+ showQuantityCounter: true,
993
+ quantityCounterStyle: 'outlined',
994
+ fulfillmentDisplay: 'carousel',
995
+ enableShippingFulfillment: true,
996
+ enableOnDemandFulfillment: true,
997
+ addToCartButtonText: 'Add to Cart',
998
+ buyNowButtonText: 'Buy Now'
999
+ }
1000
+ }
1001
+ }
1002
+ ```
1003
+
1004
+ #### Cart Component
1005
+
1006
+ ```js
1007
+ customTheme: {
1008
+ cart: {
1009
+ theme: {
1010
+ backgroundColor: '#ffffff'
1011
+ },
1012
+ layout: {
1013
+ showQuantityCounter: true,
1014
+ quantityCounterStyle: 'outlined',
1015
+ drawerHeaderText: 'Your Cart',
1016
+ goToCheckoutButtonText: 'Checkout'
1017
+ }
1018
+ }
1019
+ }
1020
+ ```
1021
+
1022
+ #### Checkout Component
1023
+
1024
+ ```js
1025
+ customTheme: {
1026
+ checkout: {
1027
+ theme: {
1028
+ backgroundColor: '#ffffff',
1029
+ checkoutCompleted: {
1030
+ customLogo: 'https://yourdomain.com/logo.png',
1031
+ customText: 'Thank you for your order!'
1032
+ }
1033
+ },
1034
+ layout: {
1035
+ emailOptIn: {
1036
+ show: true,
1037
+ checked: false,
1038
+ text: 'Email me with news'
1039
+ },
1040
+ smsOptIn: {
1041
+ show: true,
1042
+ checked: false,
1043
+ text: 'Text me updates'
1044
+ },
1045
+ allowGiftCards: true,
1046
+ drawerHeaderText: 'Checkout',
1047
+ placeOrderButtonText: 'Place Order'
1048
+ }
1049
+ }
1050
+ }
1051
+ ```
1052
+
1053
+ #### Address Component
1054
+
1055
+ ```js
1056
+ customTheme: {
1057
+ address: {
1058
+ theme: {
1059
+ backgroundColor: '#ffffff'
1060
+ }
1061
+ }
1062
+ }
1063
+ ```
1064
+
1065
+ ### Dynamic Theme Updates (Builder Mode)
1066
+
1067
+ In development with `isBuilder: true`, update themes in real-time:
1068
+
1069
+ ```js
1070
+ const client = await Elements('YOUR_API_KEY', {
1071
+ env: 'development',
1072
+ isBuilder: true
900
1073
  });
901
1074
 
1075
+ // Update global theme
1076
+ await client.builder.updateComponentGlobalConfigs({
1077
+ theme: { primaryColor: '#ff6b6b' }
1078
+ });
1079
+
1080
+ // Update component-specific themes
902
1081
  await client.builder.updateProductComponent({
903
- layout: { imagePosition: 'right' }
1082
+ layout: { addToCartButtonText: 'Add to Bag' }
1083
+ });
1084
+
1085
+ client.builder.updateCartComponent({
1086
+ layout: { drawerHeaderText: 'Shopping Bag' }
1087
+ });
1088
+
1089
+ client.builder.updateCheckoutComponent({
1090
+ layout: { placeOrderButtonText: 'Complete Purchase' }
1091
+ });
1092
+
1093
+ client.builder.updateAddressComponent({
1094
+ theme: { backgroundColor: '#f8f9fa' }
904
1095
  });
905
1096
  ```
906
1097
 
907
- ## 🔒 Proxy Configuration
1098
+ **📖 For complete theming documentation:** See [`docs/THEMING.md`](docs/THEMING.md)
908
1099
 
909
- Route API requests through your server to avoid ad blockers:
1100
+ ---
1101
+
1102
+ ## 🎁 Features Deep Dive
1103
+
1104
+ ### Product Personalization (Engraving)
1105
+
1106
+ The SDK provides a comprehensive personalization/engraving feature for products that support it. The personalization experience varies based on context:
1107
+
1108
+ #### Product View
1109
+ When browsing products, customers can add personalization through an enhanced form that includes:
1110
+ - Product information with pricing
1111
+ - Fulfillment/retailer selection (with pricing comparison)
1112
+ - Multi-line engraving inputs with character limits
1113
+ - Real-time price updates as customers select different retailers
1114
+ - Add-to-cart with personalization in one step
1115
+
1116
+ ```js
1117
+ // Personalization appears automatically for engravable products
1118
+ // Customers can add engraving text and select which retailer to fulfill from
1119
+
1120
+ // Listen for when personalization is added via add-to-cart
1121
+ window.addEventListener('lce:actions.product_add_to_cart', (event) => {
1122
+ const { hasEngraving, engravingLines } = event.detail.data;
1123
+ if (hasEngraving) {
1124
+ console.log('Customer personalized:', engravingLines);
1125
+ }
1126
+ });
1127
+ ```
1128
+
1129
+ #### Cart View
1130
+ In the cart, personalized items display:
1131
+ - Personalization text lines
1132
+ - Engraving fee (per item and total for quantity)
1133
+ - **Edit** button to modify the personalization
1134
+ - **Remove** button to remove personalization
1135
+
1136
+ ```js
1137
+ // Customers can edit or remove engraving from cart items
1138
+ window.addEventListener('lce:actions.cart_item_engraving_updated', (event) => {
1139
+ const { identifier, engravingLines } = event.detail.data;
1140
+ console.log('Cart item engraving updated:', engravingLines);
1141
+ });
1142
+ ```
1143
+
1144
+ #### Checkout View
1145
+ During checkout, personalized items show:
1146
+ - Personalization text lines (read-only)
1147
+ - Engraving fee included in pricing
1148
+ - **Remove** button only (editing not allowed in checkout)
1149
+
1150
+ **Design Decision:** Editing personalization during checkout is intentionally disabled to prevent order processing complications. Customers must return to the cart to make changes.
1151
+
1152
+ #### Theming & Configuration
1153
+
1154
+ Control personalization display through global configuration:
1155
+
1156
+ ```js
1157
+ customTheme: {
1158
+ global: {
1159
+ layout: {
1160
+ enablePersonalization: true,
1161
+ personalizationText: 'Personalize your product',
1162
+ personalizationCardStyle: 'outlined' // or 'filled'
1163
+ }
1164
+ }
1165
+ }
1166
+ ```
1167
+
1168
+ #### Key Features
1169
+ - **Smart pricing:** Automatically includes engraving fees in product price
1170
+ - **Retailer selection:** Compare prices from different retailers during personalization
1171
+ - **Character limits:** Enforces maximum characters per line
1172
+ - **Uppercase conversion:** Engraving text is automatically converted to uppercase
1173
+ - **Multi-line support:** Products can support 1 or more engraving lines
1174
+ - **Fee transparency:** Shows per-item and total fees (e.g., "$5.00 ($2.50 ea)")
1175
+
1176
+ **Note:** Personalization is automatically enabled for products that support it. The SDK handles all UI, validation, and state management.
1177
+
1178
+ ### Gift Options
1179
+
1180
+ Allow orders to be marked as gifts with custom messages:
1181
+
1182
+ ```js
1183
+ // Enable via theme
1184
+ customTheme: {
1185
+ checkout: {
1186
+ layout: {
1187
+ allowGiftOptions: true
1188
+ }
1189
+ }
1190
+ }
1191
+
1192
+ // Toggle gift mode programmatically
1193
+ await client.actions.checkout.toggleIsGift(true);
1194
+
1195
+ // Set gift message
1196
+ await client.actions.checkout.updateGiftInfo({
1197
+ recipientName: 'John Doe',
1198
+ message: 'Happy Birthday!'
1199
+ });
1200
+
1201
+ // Listen for gift toggles
1202
+ window.addEventListener('lce:actions.checkout_is_gift_toggled', (event) => {
1203
+ const { isGift } = event.detail.data;
1204
+ console.log('Order is gift:', isGift);
1205
+ });
1206
+ ```
1207
+
1208
+ ### Tips (On-Demand Delivery)
1209
+
1210
+ Allow customers to tip delivery drivers:
1211
+
1212
+ ```js
1213
+ // Tips are automatically enabled for onDemand fulfillment types
1214
+
1215
+ // Listen for tip updates
1216
+ window.addEventListener('lce:actions.checkout_tip_updated', (event) => {
1217
+ const { tipAmount, total } = event.detail.data;
1218
+ console.log(`Customer tipped $${tipAmount}`);
1219
+ });
1220
+ ```
1221
+
1222
+ Tips are calculated as a percentage or fixed amount and added to the order total.
1223
+
1224
+ ### Gift Cards
1225
+
1226
+ Accept gift card payments at checkout:
1227
+
1228
+ ```js
1229
+ // Enable via theme
1230
+ customTheme: {
1231
+ checkout: {
1232
+ layout: {
1233
+ allowGiftCards: true
1234
+ }
1235
+ }
1236
+ }
1237
+
1238
+ // Apply gift card programmatically
1239
+ await client.actions.checkout.applyGiftCard('GIFT-1234-5678-9012');
1240
+
1241
+ // Remove gift card
1242
+ await client.actions.checkout.removeGiftCard('GIFT-1234-5678-9012');
1243
+
1244
+ // Listen for gift card events
1245
+ window.addEventListener('lce:actions.checkout_gift_card_applied', (event) => {
1246
+ const { code, appliedAmount, remainingBalance } = event.detail.data;
1247
+ console.log(`Applied $${appliedAmount}, Remaining: $${remainingBalance}`);
1248
+ });
1249
+
1250
+ window.addEventListener('lce:actions.checkout_gift_card_failed', (event) => {
1251
+ const { code, error } = event.detail.data;
1252
+ console.log('Gift card failed:', error);
1253
+ });
1254
+ ```
1255
+
1256
+ ### Promo Codes
1257
+
1258
+ Apply promotional discount codes:
910
1259
 
911
1260
  ```js
1261
+ // Apply to cart
1262
+ await client.actions.cart.applyPromoCode('SUMMER20');
1263
+
1264
+ // Apply to checkout
1265
+ await client.actions.checkout.applyPromoCode('SAVE10');
1266
+
1267
+ // Remove promo code
1268
+ await client.actions.cart.removePromoCode();
1269
+
1270
+ // Listen for promo events
1271
+ window.addEventListener('lce:actions.cart_promo_code_applied', (event) => {
1272
+ const { code, discountAmount, newTotal } = event.detail.data;
1273
+ console.log(`${code} saved $${discountAmount}! New total: $${newTotal}`);
1274
+ });
1275
+
1276
+ window.addEventListener('lce:actions.cart_promo_code_failed', (event) => {
1277
+ const { code, error } = event.detail.data;
1278
+ console.log('Promo failed:', error.message);
1279
+ });
1280
+ ```
1281
+
1282
+ ### Promo Ticker
1283
+
1284
+ Display rotating promotional messages at the top of your site:
1285
+
1286
+ ```js
1287
+ // Via initialization config
912
1288
  const client = await Elements('YOUR_API_KEY', {
913
- env: 'production',
914
- proxy: {
915
- baseUrl: 'https://yourdomain.com/api/liquidcommerce',
916
- headers: {
917
- 'X-Custom-Header': 'value'
1289
+ promoTicker: [
1290
+ {
1291
+ promoCode: 'FREESHIP',
1292
+ text: ['Free Shipping Today!', 'Use code FREESHIP'],
1293
+ separator: '',
1294
+ activeFrom: '2025-01-01T00:00:00Z',
1295
+ activeUntil: '2025-12-31T23:59:59Z'
1296
+ },
1297
+ {
1298
+ promoCode: 'SAVE20',
1299
+ text: ['20% Off Sitewide', 'Limited Time Only'],
1300
+ separator: '|',
1301
+ activeFrom: '2025-06-01T00:00:00Z',
1302
+ activeUntil: '2025-06-30T23:59:59Z'
1303
+ }
1304
+ ]
1305
+ });
1306
+
1307
+ // Via auto-init
1308
+ <script
1309
+ data-liquid-commerce-elements
1310
+ data-token="YOUR_API_KEY"
1311
+ data-promo-code="FREESHIP"
1312
+ data-promo-text="Free Shipping Today!|Use code FREESHIP"
1313
+ data-promo-separator="•"
1314
+ data-promo-active-from="2025-01-01T00:00:00Z"
1315
+ data-promo-active-until="2025-12-31T23:59:59Z"
1316
+ src="https://assets-elements.liquidcommerce.us/all/elements.js"
1317
+ ></script>
1318
+ ```
1319
+
1320
+ The ticker automatically rotates messages and only shows active promotions.
1321
+
1322
+ ### Marketing Preferences
1323
+
1324
+ Allow customers to opt-in to email and SMS marketing:
1325
+
1326
+ ```js
1327
+ // Set defaults via theme
1328
+ customTheme: {
1329
+ checkout: {
1330
+ layout: {
1331
+ emailOptIn: { checked: false, visible: true },
1332
+ smsOptIn: { checked: false, visible: true }
918
1333
  }
919
1334
  }
1335
+ }
1336
+
1337
+ // Update preferences programmatically
1338
+ await client.actions.checkout.toggleMarketingPreferences('canEmail', true);
1339
+ await client.actions.checkout.toggleMarketingPreferences('canSms', true);
1340
+
1341
+ // Listen for preference changes
1342
+ window.addEventListener('lce:actions.checkout_marketing_preferences_toggled', (event) => {
1343
+ const { field, value } = event.detail.data;
1344
+ console.log(`Customer ${value ? 'opted-in' : 'opted-out'} of ${field}`);
920
1345
  });
921
1346
  ```
922
1347
 
923
- The SDK automatically handles routing and required headers. See [`docs/PROXY.md`](docs/PROXY.md) for complete proxy setup guide with Next.js examples.
1348
+ ### Purchase Minimum Alerts
924
1349
 
925
- ## 📚 Documentation
1350
+ Automatically displays alerts when a retailer has minimum purchase requirements. No configuration needed - the SDK handles this automatically based on retailer rules.
926
1351
 
927
- For detailed guides and advanced usage:
1352
+ ### Age Verification
928
1353
 
929
- - [`docs/ACTIONS.md`](docs/ACTIONS.md) - Complete actions reference with business use cases
930
- - [`docs/EVENTS.md`](docs/EVENTS.md) - Events guide with implementation examples
931
- - [`docs/BROWSER_SUPPORT.md`](docs/BROWSER_SUPPORT.md) - Detailed browser compatibility
932
- - [`docs/PROXY.md`](docs/PROXY.md) - Proxy configuration for ad blocker avoidance
1354
+ For age-restricted products (alcohol, tobacco, etc.), the SDK automatically displays age verification prompts during checkout. This is handled based on product metadata and cannot be disabled for restricted items.
933
1355
 
934
- ## 🏷️ Versioning
1356
+ ### Pre-Sale Countdown
1357
+
1358
+ For pre-sale or upcoming products, the SDK automatically displays a countdown timer until the product becomes available. Customers can add pre-sale items to cart, and the SDK handles the special fulfillment flow.
1359
+
1360
+ ```js
1361
+ // Listen for when product is added to cart
1362
+ window.addEventListener('lce:actions.product_add_to_cart', (event) => {
1363
+ const { productId } = event.detail.data;
1364
+ console.log(`Product ${productId} added to cart`);
1365
+ });
1366
+ ```
1367
+
1368
+ ---
935
1369
 
936
- This project uses Semantic Versioning. The SDK is available in two environments:
1370
+ ## 🔧 Core Capabilities
937
1371
 
938
- ### Beta Environment
939
- - Branch: `beta`
940
- - Base URL: `https://assets-elements.liquidcommerce.us/all/beta/`
941
- - Purpose: Testing and pre-release features
1372
+ The SDK includes several built-in services that work behind the scenes to provide a robust, production-ready experience.
942
1373
 
943
- ### Production Environment
944
- - Branch: `main`
945
- - Base URL: `https://assets-elements.liquidcommerce.us/all/`
946
- - Purpose: Stable releases for production use
1374
+ ### State Management
1375
+
1376
+ The SDK uses a centralized store for all state management. Access state data via actions:
1377
+
1378
+ ```js
1379
+ // Get current cart state
1380
+ const cart = await client.actions.cart.getDetails();
1381
+ console.log(cart.itemCount, cart.amounts.total, cart.amounts.giftCardTotal);
947
1382
 
948
- ### CDN Path Structure
1383
+ // Get current checkout state
1384
+ const checkout = await client.actions.checkout.getDetails();
1385
+ console.log(checkout.amounts.total, checkout.isGift, checkout.acceptedAccountCreation);
1386
+ console.log(checkout.billingSameAsShipping, checkout.marketingPreferences);
949
1387
 
1388
+ // Get current address
1389
+ const address = await client.actions.address.getDetails();
1390
+ console.log(address.formattedAddress, address.coordinates);
1391
+
1392
+ // Get product details
1393
+ const product = await client.actions.product.getDetails('00619947000020');
1394
+ console.log(product.name, product.region, product.variety, product.vintage);
1395
+ console.log(product.description, product.tastingNotes);
950
1396
  ```
951
- elements-sdk/
952
- └── all/
953
- ├── beta/
954
- │ ├── 1.2.3/elements.js
955
- │ ├── 1.2.4/elements.js
956
- │ └── elements.js (beta latest)
957
- ├── 1.2.2/elements.js (production)
958
- ├── 1.2.3/elements.js (production)
959
- └── elements.js (production latest)
1397
+
1398
+ **State is persistent:** Cart and address data persist across page reloads using localStorage.
1399
+
1400
+ ### Event System (PubSub)
1401
+
1402
+ All SDK interactions emit events through a centralized event system:
1403
+
1404
+ ```js
1405
+ // Subscribe to specific event
1406
+ window.addEventListener('lce:actions.cart_updated', (event) => {
1407
+ const { previous, current } = event.detail.data;
1408
+ console.log('Cart changed from', previous.amounts.total, 'to', current.amounts.total);
1409
+ });
1410
+
1411
+ // Subscribe to all action events
1412
+ if (window.elements) {
1413
+ window.elements.onAllActions((data, metadata) => {
1414
+ console.log('Action:', metadata.eventName, data);
1415
+ });
1416
+ }
1417
+
1418
+ // Subscribe to all form events
1419
+ if (window.elements) {
1420
+ window.elements.onAllForms((data, metadata) => {
1421
+ console.log('Form:', metadata.eventName, data);
1422
+ });
1423
+ }
1424
+ ```
1425
+
1426
+ **Event format:**
1427
+ ```js
1428
+ {
1429
+ detail: {
1430
+ data: { /* event-specific payload */ },
1431
+ metadata: {
1432
+ eventName: 'lce:actions.cart_updated',
1433
+ timestamp: 1699564800000,
1434
+ source: 'sdk'
1435
+ }
1436
+ }
1437
+ }
1438
+ ```
1439
+
1440
+ ### Telemetry & Analytics
1441
+
1442
+ The SDK automatically tracks user interactions and performance metrics:
1443
+
1444
+ - **User interactions:** Add to cart, checkout started, checkout completed
1445
+ - **Performance metrics:** Component load times, API response times
1446
+ - **Error tracking:** Failed API calls, validation errors
1447
+
1448
+ **Note:** The SDK includes automatic Google Tag Manager (GTM) integration that tracks e-commerce events. GTM configuration is managed through your LiquidCommerce dashboard, not the client initialization.
1449
+
1450
+ **Custom Analytics:**
1451
+
1452
+ ```js
1453
+ // Listen to events for custom analytics tracking
1454
+ window.addEventListener('lce:actions.product_add_to_cart', (event) => {
1455
+ const { productId, price, quantity } = event.detail.data;
1456
+
1457
+ // Track with your analytics provider
1458
+ gtag('event', 'add_to_cart', {
1459
+ currency: 'USD',
1460
+ value: price * quantity,
1461
+ items: [{ item_id: productId, quantity }]
1462
+ });
1463
+
1464
+ // Or Segment
1465
+ analytics.track('Product Added', {
1466
+ product_id: productId,
1467
+ price,
1468
+ quantity
1469
+ });
1470
+ });
960
1471
  ```
961
1472
 
962
- ## 🎭 Demo Pages
1473
+ ### Circuit Breaker
963
1474
 
964
- The SDK includes ready-to-use demo pages in the `demo/` folder that showcase different implementation approaches:
1475
+ The SDK includes a circuit breaker pattern to prevent cascading failures:
965
1476
 
966
- ### Simple Demo (`demo/simple.html`)
1477
+ ```js
1478
+ // Automatically handles API failures
1479
+ // - After 5 consecutive failures, circuit opens
1480
+ // - Requests fail fast without hitting the API
1481
+ // - After 30 seconds, circuit half-opens
1482
+ // - Next successful request closes the circuit
1483
+ ```
1484
+
1485
+ **Circuit states:**
1486
+ - **Closed:** Normal operation, all requests go through
1487
+ - **Open:** API is failing, requests fail fast
1488
+ - **Half-Open:** Testing if API recovered, limited requests allowed
1489
+
1490
+ This protects your site from slowdowns when the API is experiencing issues.
1491
+
1492
+ ### Fingerprinting
1493
+
1494
+ The SDK generates a unique device fingerprint for fraud prevention and analytics:
1495
+
1496
+ ```js
1497
+ // Automatically tracked:
1498
+ // - Browser fingerprint
1499
+ // - Device characteristics
1500
+ // - Session information
1501
+
1502
+ // Used for:
1503
+ // - Fraud detection
1504
+ // - Cart persistence across devices
1505
+ // - Personalization
1506
+ ```
1507
+
1508
+ Fingerprinting is handled automatically and requires no configuration.
1509
+
1510
+ ### Authentication
1511
+
1512
+ The SDK handles authentication automatically using your API key:
1513
+
1514
+ ```js
1515
+ const client = await Elements('YOUR_API_KEY', {
1516
+ env: 'production'
1517
+ });
1518
+
1519
+ // All API requests include:
1520
+ // - API key authentication
1521
+ // - CORS headers
1522
+ // - Request signing (when required)
1523
+ ```
1524
+
1525
+ **Token refresh:** The SDK automatically handles token expiration and refresh.
1526
+
1527
+ ### Logger
967
1528
 
968
- Demonstrates **auto-initialization** using data attributes - the easiest way to get started:
1529
+ Built-in logging system with configurable levels:
1530
+
1531
+ ```js
1532
+ const client = await Elements('YOUR_API_KEY', {
1533
+ debugMode: 'console' // 'none' | 'console' | 'panel'
1534
+ });
1535
+
1536
+ // Debug mode options:
1537
+ // - 'none': No logging (production default)
1538
+ // - 'console': Logs to browser console
1539
+ // - 'panel': Shows visual debug panel + console logs
1540
+ ```
1541
+
1542
+ **Console debug output:**
1543
+ ```
1544
+ [LCE SDK] Product loaded: product-123
1545
+ [LCE SDK] Cart updated: 3 items, $45.99
1546
+ [LCE SDK] Checkout started
1547
+ [LCE SDK] API call: POST /cart/add (152ms)
1548
+ ```
1549
+
1550
+ **Debug panel:**
1551
+ - Real-time event stream
1552
+ - API call inspector
1553
+ - State viewer
1554
+ - Performance metrics
1555
+
1556
+ ### Command Pattern
1557
+
1558
+ The SDK uses a command pattern for all operations:
1559
+
1560
+ ```js
1561
+ // Commands are:
1562
+ // - Queued for execution
1563
+ // - Retried on failure
1564
+ // - Logged for debugging
1565
+ // - Cancelable
1566
+
1567
+ // Example: Adding to cart
1568
+ // 1. Command created: AddToCartCommand
1569
+ // 2. Command queued
1570
+ // 3. Command executed
1571
+ // 4. Success event emitted
1572
+ // 5. UI updated
1573
+
1574
+ // This ensures:
1575
+ // - Consistent error handling
1576
+ // - Automatic retries
1577
+ // - Full audit trail
1578
+ ```
1579
+
1580
+ ### Component Factory
1581
+
1582
+ Components are created on-demand using a factory pattern:
1583
+
1584
+ ```js
1585
+ // When you call:
1586
+ await client.injectProductElement([
1587
+ { containerId: 'pdp-1', identifier: 'product-123' }
1588
+ ]);
1589
+
1590
+ // The SDK:
1591
+ // 1. Creates a ProductComponent instance
1592
+ // 2. Registers it with the factory
1593
+ // 3. Injects it into the DOM
1594
+ // 4. Attaches event listeners
1595
+ // 5. Loads product data
1596
+ // 6. Renders the component
1597
+
1598
+ // Components are:
1599
+ // - Lazily loaded
1600
+ // - Automatically cleaned up
1601
+ // - Reusable across pages
1602
+ ```
1603
+
1604
+ ### Singleton Manager
1605
+
1606
+ Core services are managed as singletons:
1607
+
1608
+ ```js
1609
+ // These services are initialized once and reused:
1610
+ // - ApiClient
1611
+ // - Store
1612
+ // - PubSub
1613
+ // - Logger
1614
+ // - Telemetry
1615
+ // - CircuitBreaker
1616
+ // - Fingerprint
1617
+ // - Auth
1618
+
1619
+ // This ensures:
1620
+ // - Consistent state
1621
+ // - Efficient memory usage
1622
+ // - No duplicate API calls
1623
+ ```
1624
+
1625
+ ---
1626
+
1627
+ ## 🏗️ Integration Patterns
1628
+
1629
+ ### React Integration
1630
+
1631
+ ```jsx
1632
+ import { useEffect, useState } from 'react';
1633
+ import { Elements } from '@liquidcommerce/elements-sdk';
1634
+
1635
+ function ProductPage({ productId }) {
1636
+ const [client, setClient] = useState(null);
1637
+
1638
+ useEffect(() => {
1639
+ async function initSDK() {
1640
+ const elementsClient = await Elements(process.env.REACT_APP_LCE_API_KEY, {
1641
+ env: 'production'
1642
+ });
1643
+ setClient(elementsClient);
1644
+
1645
+ // Inject product
1646
+ await elementsClient.injectProductElement([
1647
+ { containerId: 'product-container', identifier: productId }
1648
+ ]);
1649
+
1650
+ // Create cart button
1651
+ elementsClient.ui.cartButton('cart-button', true);
1652
+ }
1653
+
1654
+ initSDK();
1655
+
1656
+ // Cleanup
1657
+ return () => {
1658
+ // SDK handles cleanup automatically
1659
+ };
1660
+ }, [productId]);
1661
+
1662
+ return (
1663
+ <div>
1664
+ <div id="cart-button"></div>
1665
+ <div id="product-container"></div>
1666
+ </div>
1667
+ );
1668
+ }
1669
+ ```
1670
+
1671
+ ### Vue Integration
1672
+
1673
+ ```vue
1674
+ <template>
1675
+ <div>
1676
+ <div ref="cartButton"></div>
1677
+ <div ref="productContainer"></div>
1678
+ </div>
1679
+ </template>
1680
+
1681
+ <script>
1682
+ import { Elements } from '@liquidcommerce/elements-sdk';
1683
+
1684
+ export default {
1685
+ name: 'ProductPage',
1686
+ props: ['productId'],
1687
+ async mounted() {
1688
+ this.client = await Elements(process.env.VUE_APP_LCE_API_KEY, {
1689
+ env: 'production'
1690
+ });
1691
+
1692
+ await this.client.injectProductElement([
1693
+ { containerId: this.$refs.productContainer.id, identifier: this.productId }
1694
+ ]);
1695
+
1696
+ this.client.ui.cartButton(this.$refs.cartButton.id, true);
1697
+ }
1698
+ }
1699
+ </script>
1700
+ ```
1701
+
1702
+ ### Next.js Integration
1703
+
1704
+ ```tsx
1705
+ 'use client';
1706
+
1707
+ import { useEffect } from 'react';
1708
+
1709
+ export default function ProductPage({ productId }: { productId: string }) {
1710
+ useEffect(() => {
1711
+ // Load SDK script
1712
+ const script = document.createElement('script');
1713
+ script.src = 'https://assets-elements.liquidcommerce.us/all/elements.js';
1714
+ script.async = true;
1715
+ script.onload = async () => {
1716
+ const client = await (window as any).Elements(process.env.NEXT_PUBLIC_LCE_API_KEY, {
1717
+ env: 'production'
1718
+ });
1719
+
1720
+ await client.injectProductElement([
1721
+ { containerId: 'product-container', identifier: productId }
1722
+ ]);
1723
+
1724
+ client.ui.floatingCartButton(true);
1725
+ };
1726
+ document.body.appendChild(script);
1727
+
1728
+ return () => {
1729
+ document.body.removeChild(script);
1730
+ };
1731
+ }, [productId]);
1732
+
1733
+ return <div id="product-container"></div>;
1734
+ }
1735
+ ```
1736
+
1737
+ ### WordPress Integration
969
1738
 
970
1739
  ```html
971
- <!-- Auto-init with data attributes -->
1740
+ <!-- In your theme's header.php or functions.php -->
972
1741
  <script
973
1742
  data-liquid-commerce-elements
974
- data-token="YOUR_API_KEY"
975
- data-env="development"
976
- data-enable-debugging
977
- src="../umd/elements.js"
1743
+ data-token="<?php echo get_option('lce_api_key'); ?>"
1744
+ data-env="production"
1745
+ src="https://assets-elements.liquidcommerce.us/all/elements.js"
978
1746
  ></script>
1747
+
1748
+ <!-- In your product template -->
1749
+ <div data-lce-product="<?php echo get_post_meta(get_the_ID(), 'product_upc', true); ?>"></div>
979
1750
  ```
980
1751
 
981
- **Features shown:**
982
- - Auto-initialization with data attributes
983
- - Multiple product mapping methods (data attributes, JSON script, annotated elements)
984
- - Event listening for actions and forms
985
- - Basic container setup for products, cart, and checkout
1752
+ ### Shopify Integration
1753
+
1754
+ ```html
1755
+ <!-- In theme.liquid -->
1756
+ <script
1757
+ data-liquid-commerce-elements
1758
+ data-token="{{ settings.lce_api_key }}"
1759
+ data-env="production"
1760
+ src="https://assets-elements.liquidcommerce.us/all/elements.js"
1761
+ ></script>
986
1762
 
987
- **Best for:** Quick prototyping, simple integrations, getting familiar with the SDK
1763
+ <!-- In product template -->
1764
+ <div data-lce-product="{{ product.barcode }}"></div>
1765
+ ```
988
1766
 
989
- ### Advanced Demo (`demo/advanced.html`)
1767
+ ### Multi-Page Applications
990
1768
 
991
- Demonstrates **programmatic initialization** for full control:
1769
+ For SPAs and multi-page apps, initialize once and reuse:
992
1770
 
993
- ```javascript
994
- const client = await window.Elements(API_KEY, {
995
- env: "development",
996
- enableDebugging: true,
997
- customTheme: { /* theme config */ }
998
- });
1771
+ ```js
1772
+ // app.js (initialize once)
1773
+ let elementsClient = null;
1774
+
1775
+ async function getElementsClient() {
1776
+ if (!elementsClient) {
1777
+ elementsClient = await Elements('YOUR_API_KEY', {
1778
+ env: 'production'
1779
+ });
1780
+ }
1781
+ return elementsClient;
1782
+ }
999
1783
 
1000
- // Programmatic component injection
1001
- client.buttons.openCart("buttons-container");
1784
+ // product-page.js
1785
+ const client = await getElementsClient();
1002
1786
  await client.injectProductElement([
1003
- { containerId: "pdp-container", identifier: '00619947000020' }
1787
+ { containerId: 'pdp-1', identifier: productId }
1004
1788
  ]);
1005
- await client.injectCheckoutElement("checkout-container");
1789
+
1790
+ // cart-page.js
1791
+ const client = await getElementsClient();
1792
+ await client.injectCartElement('cart-container');
1006
1793
  ```
1007
1794
 
1008
- **Features shown:**
1009
- - Manual client initialization with full configuration
1010
- - Programmatic component injection
1011
- - Builder methods for theme updates (commented examples)
1012
- - Advanced event handling
1013
- - Dynamic theme updates
1795
+ ---
1796
+
1797
+ ## 🚨 Error Handling
1798
+
1799
+ ### Initialization Errors
1014
1800
 
1015
- **Best for:** Complex integrations, custom workflows, theme customization, production implementations
1801
+ ```js
1802
+ try {
1803
+ const client = await Elements('YOUR_API_KEY', {
1804
+ env: 'production'
1805
+ });
1806
+ } catch (error) {
1807
+ if (error.message.includes('Invalid API key')) {
1808
+ console.error('Authentication failed');
1809
+ } else if (error.message.includes('Network')) {
1810
+ console.error('Network error - check connectivity');
1811
+ } else {
1812
+ console.error('SDK initialization failed:', error);
1813
+ }
1814
+ }
1815
+ ```
1016
1816
 
1017
- ### Running the Demos
1817
+ ### Action Errors
1018
1818
 
1019
- 1. **Clone the repository**
1020
- 2. **Open demo files** in your browser
1021
- 3. **Update API keys** with your own credentials
1022
- 4. **Modify environment** settings as needed (`development`, `staging`, `production`)
1819
+ All actions emit failure events with detailed error information:
1023
1820
 
1024
- The demos use local UMD builds (`../umd/elements.js`) but can be easily switched to CDN URLs for testing.
1821
+ ```js
1822
+ // Product loaded successfully
1823
+ window.addEventListener('lce:actions.product_loaded', (event) => {
1824
+ const { identifier, productData } = event.detail.data;
1825
+ console.log(`Product ${identifier} loaded successfully`);
1826
+ });
1025
1827
 
1026
- ## 🛠️ Development Scripts
1828
+ // Cart action failure
1829
+ window.addEventListener('lce:actions.cart_product_add_failed', (event) => {
1830
+ const { identifiers, error } = event.detail.data;
1831
+ console.error('Failed to add products:', error);
1832
+
1833
+ // Show user-friendly message
1834
+ showNotification('Could not add to cart. Please try again.', 'error');
1835
+ });
1027
1836
 
1028
- For SDK development and maintenance, the following npm/pnpm scripts are available:
1837
+ // Checkout failure
1838
+ window.addEventListener('lce:actions.checkout_submit_failed', (event) => {
1839
+ const { error, reason } = event.detail.data;
1840
+ console.error('Checkout failed:', reason);
1841
+
1842
+ // Handle specific errors
1843
+ if (reason.includes('payment')) {
1844
+ showNotification('Payment declined. Please check your card details.', 'error');
1845
+ } else if (reason.includes('inventory')) {
1846
+ showNotification('Some items are no longer available.', 'warning');
1847
+ } else {
1848
+ showNotification('Checkout failed. Please try again.', 'error');
1849
+ }
1850
+ });
1029
1851
 
1030
- ### Build Commands
1852
+ // Address validation failure
1853
+ window.addEventListener('lce:actions.address_failed', (event) => {
1854
+ const { error } = event.detail.data;
1855
+ console.error('Address validation failed:', error);
1856
+ showNotification('Please enter a valid address.', 'error');
1857
+ });
1031
1858
 
1032
- **`build`** - Production build
1033
- ```bash
1034
- pnpm run build
1859
+ // Promo code failure
1860
+ window.addEventListener('lce:actions.cart_promo_code_failed', (event) => {
1861
+ const { code, error } = event.detail.data;
1862
+ console.error(`Promo code ${code} failed:`, error);
1863
+
1864
+ if (error.includes('expired')) {
1865
+ showNotification('This promo code has expired.', 'warning');
1866
+ } else if (error.includes('invalid')) {
1867
+ showNotification('Invalid promo code.', 'error');
1868
+ } else if (error.includes('minimum')) {
1869
+ showNotification('Cart minimum not met for this promo.', 'warning');
1870
+ }
1871
+ });
1035
1872
  ```
1036
- - Creates optimized ESM and UMD bundles for production
1037
- - Generates TypeScript declarations
1038
- - Enables minification and compression
1039
- - Removes console logs and debugging code
1040
- - **Output:** `dist/index.esm.js` (ESM) + `umd/elements.js` (UMD)
1041
1873
 
1042
- **`build:dev`** - Development build
1043
- ```bash
1044
- pnpm run build:dev
1874
+ ### Network Error Recovery
1875
+
1876
+ ```js
1877
+ let retryCount = 0;
1878
+ const maxRetries = 3;
1879
+
1880
+ async function addProductWithRetry(productParams) {
1881
+ try {
1882
+ await client.actions.cart.addProduct(productParams);
1883
+ } catch (error) {
1884
+ if (retryCount < maxRetries && error.message.includes('Network')) {
1885
+ retryCount++;
1886
+ console.log(`Retrying... Attempt ${retryCount}/${maxRetries}`);
1887
+ setTimeout(() => addProductWithRetry(productParams), 1000 * retryCount);
1888
+ } else {
1889
+ console.error('Failed after retries:', error);
1890
+ showNotification('Network error. Please check your connection.', 'error');
1891
+ }
1892
+ }
1893
+ }
1045
1894
  ```
1046
- - Creates unminified bundles with source maps
1047
- - Preserves console logs and debugging code
1048
- - Faster build times for development
1049
- - **Output:** Same as build but with debugging enabled
1050
1895
 
1051
- **`dev`** - Development with watch mode
1052
- ```bash
1053
- pnpm run dev
1896
+ ### Global Error Handler
1897
+
1898
+ ```js
1899
+ // Listen to all failed events
1900
+ window.addEventListener('lce:actions.cart_failed', handleError);
1901
+ window.addEventListener('lce:actions.checkout_failed', handleError);
1902
+ window.addEventListener('lce:actions.address_failed', handleError);
1903
+ window.addEventListener('lce:actions.cart_product_add_failed', handleError);
1904
+
1905
+ function handleError(event) {
1906
+ const { error, context } = event.detail.data;
1907
+
1908
+ // Log to error tracking service
1909
+ if (window.Sentry) {
1910
+ Sentry.captureException(error, {
1911
+ tags: { sdk: 'liquid-commerce' },
1912
+ extra: context
1913
+ });
1914
+ }
1915
+
1916
+ // Show user notification
1917
+ showNotification('Something went wrong. Please try again.', 'error');
1918
+ }
1054
1919
  ```
1055
- - Same as `build:dev` but watches for file changes
1056
- - Automatically rebuilds on source code changes
1057
- - **Best for:** Active development
1058
1920
 
1059
- ### Code Quality Commands
1921
+ ---
1060
1922
 
1061
- **`lint`** - Lint and auto-fix code
1062
- ```bash
1063
- pnpm run lint
1923
+ ## Performance & Best Practices
1924
+
1925
+ ### Lazy Loading Components
1926
+
1927
+ Only inject components when needed:
1928
+
1929
+ ```js
1930
+ // ❌ Don't inject all components upfront
1931
+ await client.injectProductElement([/* 50 products */]);
1932
+ await client.injectCartElement('cart');
1933
+ await client.injectCheckoutElement('checkout');
1934
+
1935
+ // ✅ Inject components as user navigates
1936
+ // On product page:
1937
+ await client.injectProductElement([{ containerId: 'pdp', identifier: productId }]);
1938
+
1939
+ // On cart page (when user clicks cart):
1940
+ await client.injectCartElement('cart');
1941
+
1942
+ // On checkout (when user proceeds):
1943
+ await client.injectCheckoutElement('checkout');
1064
1944
  ```
1065
- - Uses Biome to lint TypeScript/JavaScript files
1066
- - Automatically fixes fixable issues
1067
- - Enforces code style and catches common errors
1068
1945
 
1069
- **`format`** - Format code
1070
- ```bash
1071
- pnpm run format
1946
+ ### Reuse Client Instance
1947
+
1948
+ Initialize once, use everywhere:
1949
+
1950
+ ```js
1951
+ // ❌ Don't create multiple clients
1952
+ // page1.js
1953
+ const client1 = await Elements('KEY', { env: 'production' });
1954
+ // page2.js
1955
+ const client2 = await Elements('KEY', { env: 'production' });
1956
+
1957
+ // ✅ Create once, reuse
1958
+ // app.js
1959
+ window.lceClient = await Elements('KEY', { env: 'production' });
1960
+
1961
+ // page1.js
1962
+ const client = window.lceClient;
1963
+ await client.injectProductElement([...]);
1964
+
1965
+ // page2.js
1966
+ const client = window.lceClient;
1967
+ await client.injectCartElement('cart');
1072
1968
  ```
1073
- - Uses Biome to format all source files
1074
- - Ensures consistent code formatting
1075
- - Applies formatting rules defined in `biome.json`
1076
1969
 
1077
- **`check`** - Combined linting and formatting
1078
- ```bash
1079
- pnpm run check
1970
+ ### Batch Product Injections
1971
+
1972
+ Group product injections together:
1973
+
1974
+ ```js
1975
+ // ❌ Don't inject products one by one
1976
+ await client.injectProductElement([{ containerId: 'p1', identifier: 'id1' }]);
1977
+ await client.injectProductElement([{ containerId: 'p2', identifier: 'id2' }]);
1978
+ await client.injectProductElement([{ containerId: 'p3', identifier: 'id3' }]);
1979
+
1980
+ // ✅ Inject all products at once
1981
+ await client.injectProductElement([
1982
+ { containerId: 'p1', identifier: 'id1' },
1983
+ { containerId: 'p2', identifier: 'id2' },
1984
+ { containerId: 'p3', identifier: 'id3' }
1985
+ ]);
1080
1986
  ```
1081
- - Runs both linting and formatting in one command
1082
- - Auto-fixes issues and formats code
1083
- - **Recommended before commits**
1084
1987
 
1085
- **`fl`** - Format, lint, and build (Fast Loop)
1086
- ```bash
1087
- pnpm run fl
1988
+ ### Optimize Event Listeners
1989
+
1990
+ Use event delegation instead of multiple listeners:
1991
+
1992
+ ```js
1993
+ // ❌ Don't listen to every event
1994
+ window.addEventListener('lce:actions.product_loaded', handler);
1995
+ window.addEventListener('lce:actions.product_add_to_cart', handler);
1996
+ window.addEventListener('lce:actions.cart_updated', handler);
1997
+ // ... 20 more listeners
1998
+
1999
+ // ✅ Use consolidated listeners
2000
+ window.elements.onAllActions((data, metadata) => {
2001
+ switch (metadata.eventName) {
2002
+ case 'lce:actions.product_loaded':
2003
+ handleProductLoad(data);
2004
+ break;
2005
+ case 'lce:actions.product_add_to_cart':
2006
+ handleAddToCart(data);
2007
+ break;
2008
+ case 'lce:actions.cart_updated':
2009
+ handleCartUpdate(data);
2010
+ break;
2011
+ }
2012
+ });
1088
2013
  ```
1089
- - Combines `check` + `build:dev`
1090
- - Complete code quality check + development build
1091
- - **Perfect for:** Pre-commit workflow
1092
2014
 
1093
- ### Maintenance Commands
2015
+ ### Defer Non-Critical Operations
1094
2016
 
1095
- **`clean`** - Clean build outputs
1096
- ```bash
1097
- pnpm run clean
2017
+ Load SDK after critical page content:
2018
+
2019
+ ```html
2020
+ <!-- ❌ Don't load SDK in <head> -->
2021
+ <head>
2022
+ <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
2023
+ </head>
2024
+
2025
+ <!-- ✅ Load SDK with defer or at end of body -->
2026
+ <head>
2027
+ <script defer src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
2028
+ </head>
2029
+
2030
+ <!-- Or -->
2031
+ <body>
2032
+ <!-- Your page content -->
2033
+ <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
2034
+ </body>
1098
2035
  ```
1099
- - Removes `dist/` and `umd/` directories
1100
- - **Use when:** Build artifacts are corrupted
1101
2036
 
1102
- **`clean:hard`** - Complete reset
1103
- ```bash
1104
- pnpm run clean:hard
2037
+ ### Use Auto-Init for Simple Cases
2038
+
2039
+ Auto-init is optimized for performance:
2040
+
2041
+ ```html
2042
+ <!-- ✅ Auto-init is the fastest way for simple setups -->
2043
+ <div data-lce-product="00619947000020"></div>
2044
+ <div data-lce-product="00832889005513"></div>
2045
+
2046
+ <script
2047
+ data-liquid-commerce-elements
2048
+ data-token="YOUR_API_KEY"
2049
+ data-env="production"
2050
+ src="https://assets-elements.liquidcommerce.us/all/elements.js"
2051
+ ></script>
1105
2052
  ```
1106
- - Removes build outputs AND `node_modules/`
1107
- - Reinstalls all dependencies with `pnpm install`
1108
- - Runs a fresh production build
1109
- - **Use when:** Dependency issues or major updates
1110
2053
 
1111
- **`changelog`** - Generate changelog
1112
- ```bash
1113
- pnpm run changelog
2054
+ ### Avoid Unnecessary Re-renders
2055
+
2056
+ Don't repeatedly inject the same component:
2057
+
2058
+ ```js
2059
+ // ❌ Don't re-inject on every state change
2060
+ function updateProduct() {
2061
+ setProductId(newId);
2062
+ await client.injectProductElement([{ containerId: 'pdp', identifier: newId }]);
2063
+ }
2064
+
2065
+ // ✅ Components update automatically on state changes
2066
+ // Just inject once
2067
+ useEffect(() => {
2068
+ client.injectProductElement([{ containerId: 'pdp', identifier: productId }]);
2069
+ }, []); // Empty deps - inject once
2070
+
2071
+ // Product will auto-update when you call actions
2072
+ await client.actions.cart.addProduct([...]);
1114
2073
  ```
1115
- - Generates `CHANGELOG.md` from conventional commits
1116
- - Uses Angular commit convention
1117
- - **Use when:** Preparing releases
1118
2074
 
1119
- ### Build Configuration
2075
+ ### Cache Frequently Accessed Data
1120
2076
 
1121
- The build system uses **Rollup** with different configurations:
2077
+ ```js
2078
+ // ❌ Don't repeatedly fetch the same data
2079
+ async function showCartTotal() {
2080
+ const cart = await client.actions.cart.getDetails();
2081
+ return cart.amounts.total;
2082
+ }
2083
+
2084
+ // ✅ Use UI helpers that auto-update
2085
+ client.ui.cartSubtotal('cart-total-display');
2086
+ client.ui.cartItemsCount('cart-count-display');
2087
+
2088
+ // Or cache and listen to updates
2089
+ let cachedCart = await client.actions.cart.getDetails();
2090
+ window.addEventListener('lce:actions.cart_updated', (event) => {
2091
+ cachedCart = event.detail.data.current;
2092
+ });
2093
+ ```
1122
2094
 
1123
- #### ESM Build (`dist/index.esm.js`)
1124
- - **Target:** Modern bundlers (Vite, Webpack, etc.)
1125
- - **Format:** ES Modules
1126
- - **Optimizations:** Tree shaking, modern syntax
1127
- - **Use case:** NPM package imports
2095
+ ### Use CDN for Production
1128
2096
 
1129
- #### UMD Build (`umd/elements.js`)
1130
- - **Target:** Direct browser usage
1131
- - **Format:** Universal Module Definition
1132
- - **Global:** `window.LiquidCommerceElements`
1133
- - **Optimizations:** Maximum browser compatibility
1134
- - **Use case:** CDN distribution, `<script>` tags
2097
+ Always use CDN in production for optimal caching:
1135
2098
 
1136
- #### Development vs Production
1137
- - **Development:** Source maps, preserved logging, faster builds
1138
- - **Production:** Minified, compressed, optimized for size
2099
+ ```js
2100
+ // CDN (recommended)
2101
+ <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
1139
2102
 
1140
- ### Recommended Workflows
2103
+ // Don't self-host unless necessary
2104
+ <script src="/static/elements.js"></script>
2105
+ ```
1141
2106
 
1142
- **Development Workflow:**
1143
- ```bash
1144
- # Start development
1145
- pnpm run dev
2107
+ ### Minimize Theme Complexity
1146
2108
 
1147
- # Before committing
1148
- pnpm run fl
2109
+ Simpler themes = faster rendering:
2110
+
2111
+ ```js
2112
+ // ❌ Don't override every style property
2113
+ customTheme: {
2114
+ global: {
2115
+ colors: { /* 20 color overrides */ },
2116
+ typography: { /* 15 typography overrides */ },
2117
+ shadows: { /* 10 shadow overrides */ },
2118
+ // ... 100 more overrides
2119
+ }
2120
+ }
2121
+
2122
+ // ✅ Override only what's necessary
2123
+ customTheme: {
2124
+ global: {
2125
+ colors: {
2126
+ primary: '#007bff',
2127
+ secondary: '#6c757d'
2128
+ }
2129
+ }
2130
+ }
1149
2131
  ```
1150
2132
 
1151
- **Release Workflow:**
1152
- ```bash
1153
- # Clean and build for release
1154
- pnpm run clean:hard
2133
+ ### Monitor Performance
2134
+
2135
+ Track SDK performance in production:
2136
+
2137
+ ```js
2138
+ // Measure initialization time
2139
+ const start = performance.now();
2140
+ const client = await Elements('YOUR_API_KEY', { env: 'production' });
2141
+ console.log(`SDK initialized in ${performance.now() - start}ms`);
2142
+
2143
+ // Track component load times
2144
+ window.addEventListener('lce:actions.product_loaded', (event) => {
2145
+ const { loadTime } = event.detail.metadata;
2146
+ console.log(`Product loaded in ${loadTime}ms`);
2147
+
2148
+ // Send to analytics
2149
+ analytics.track('SDK Component Load', {
2150
+ component: 'product',
2151
+ duration: loadTime
2152
+ });
2153
+ });
2154
+ ```
2155
+
2156
+ ### Production Checklist
2157
+
2158
+ Before going live:
2159
+
2160
+ - ✅ Set `env: 'production'`
2161
+ - ✅ Set `debugMode: 'none'` (or omit)
2162
+ - ✅ Use CDN script URL
2163
+ - ✅ Pin to specific version (optional but recommended)
2164
+ - ✅ Configure proxy if using ad blockers
2165
+ - ✅ Test error handling
2166
+ - ✅ Verify event tracking
2167
+ - ✅ Check cart persistence
2168
+ - ✅ Test on target browsers
2169
+ - ✅ Measure performance metrics
1155
2170
 
1156
- # Generate changelog
1157
- pnpm run changelog
2171
+ **Production-ready init:**
1158
2172
 
1159
- # Build is run automatically on publish
2173
+ ```js
2174
+ const client = await Elements('YOUR_PRODUCTION_API_KEY', {
2175
+ env: 'production',
2176
+ debugMode: 'none',
2177
+ customTheme: { /* minimal overrides */ },
2178
+ proxy: { baseUrl: 'https://yourdomain.com/api/proxy' }
2179
+ });
1160
2180
  ```
1161
2181
 
1162
- **Troubleshooting:**
1163
- ```bash
1164
- # If builds are failing
1165
- pnpm run clean:hard
2182
+ **📖 For debugging and troubleshooting:** See [`docs/TROUBLESHOOTING.md`](docs/TROUBLESHOOTING.md) for comprehensive problem-solving guide.
2183
+
2184
+ ---
1166
2185
 
1167
- # For code quality issues
1168
- pnpm run check
2186
+ ## 🔒 Proxy Configuration
2187
+
2188
+ Route API requests through your server to avoid ad blockers:
2189
+
2190
+ ```js
2191
+ const client = await Elements('YOUR_API_KEY', {
2192
+ env: 'production',
2193
+ proxy: {
2194
+ baseUrl: 'https://yourdomain.com/api/liquidcommerce',
2195
+ headers: {
2196
+ 'X-Custom-Header': 'value'
2197
+ }
2198
+ }
2199
+ });
1169
2200
  ```
1170
2201
 
2202
+ The SDK automatically handles routing and required headers. See [`docs/PROXY.md`](docs/PROXY.md) for complete proxy setup guide with Next.js examples.
2203
+
2204
+ ## 📚 Documentation
2205
+
2206
+ **📖 Complete Documentation:**
2207
+
2208
+ - **[Documentation Index](docs/DOCUMENTATION_INDEX.md)** - Complete guide to all documentation
2209
+ - **[Configuration Reference](docs/CONFIGURATION.md)** - All configuration options with TypeScript types
2210
+ - **[Theming Guide](docs/THEMING.md)** - Complete customization reference
2211
+ - **[Actions Reference](docs/ACTIONS.md)** - Programmatic control with business use cases
2212
+ - **[Events Reference](docs/EVENTS.md)** - Event system and tracking guide
2213
+ - **[Troubleshooting Guide](docs/TROUBLESHOOTING.md)** - Common issues and solutions
2214
+ - **[Browser Support](docs/BROWSER_SUPPORT.md)** - Detailed browser compatibility
2215
+ - **[Proxy Setup](docs/PROXY.md)** - Ad blocker avoidance configuration
2216
+
2217
+ ---
2218
+
2219
+ ## 🏷️ Versioning
2220
+
2221
+ This project uses Semantic Versioning. Two CDN environments are available:
2222
+
2223
+ - **Production:** `https://assets-elements.liquidcommerce.us/all/elements.js` (stable)
2224
+ - **Beta:** `https://assets-elements.liquidcommerce.us/all/beta/elements.js` (pre-release)
2225
+
1171
2226
  ## 💬 Support
1172
2227
 
1173
2228
  If you need help with your API key, environment selection, or implementation, contact your LiquidCommerce representative.