@liquidcommerce/elements-sdk 2.2.0-beta.4 → 2.2.0-beta.40

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