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