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

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