@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.
- package/README.md +1681 -568
- package/dist/index.esm.js +10716 -8124
- 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 +16 -13
- 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 +127 -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/cart.interface.d.ts +1 -0
- package/dist/types/core/pubsub/interfaces/checkout.interface.d.ts +46 -6
- package/dist/types/core/pubsub/interfaces/core.interface.d.ts +2 -3
- package/dist/types/core/pubsub/interfaces/product.interface.d.ts +43 -6
- package/dist/types/core/store/interfaces/cart.interface.d.ts +1 -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 +18 -7
- 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/elements-client-helper.d.ts +3 -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/cloud/product.interface.d.ts +2 -0
- package/dist/types/interfaces/configs/checkout.interface.d.ts +1 -1
- package/dist/types/interfaces/core.interface.d.ts +17 -11
- 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-footer.component.d.ts +1 -0
- package/dist/types/modules/cart/components/cart-item.component.d.ts +2 -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/checkout-summary-section.component.d.ts +2 -0
- 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-items.component.d.ts +1 -0
- 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/theme-provider/services/font-manager.service.d.ts +1 -0
- 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 +4 -9
- package/dist/types/modules/ui-components/lce-element/lce-element.component.d.ts +2 -0
- package/dist/types/static/icon/index.d.ts +0 -1
- package/dist/types/utils/format.d.ts +2 -1
- package/docs/ACTIONS.md +1273 -0
- package/docs/BROWSER_SUPPORT.md +279 -0
- package/docs/CONFIGURATION.md +613 -0
- package/docs/DOCUMENTATION_INDEX.md +311 -0
- package/docs/EVENTS.md +765 -0
- package/docs/PROXY.md +228 -0
- package/docs/THEMING.md +592 -0
- package/docs/TROUBLESHOOTING.md +772 -0
- package/package.json +17 -17
- 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,605 @@ 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
|
+
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
|
-
|
|
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
|
-
|
|
435
|
+
📖 See [`docs/BROWSER_SUPPORT.md`](docs/BROWSER_SUPPORT.md) for detailed compatibility.
|
|
441
436
|
|
|
442
|
-
|
|
437
|
+
## ⚙️ Configuration
|
|
443
438
|
|
|
444
|
-
|
|
439
|
+
### Basic Configuration
|
|
445
440
|
|
|
446
|
-
|
|
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
|
-
|
|
451
|
+
### Environment Options
|
|
449
452
|
|
|
450
453
|
```js
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
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
|
-
|
|
521
|
+
**📖 For complete theming options:** See [`docs/THEMING.md`](docs/THEMING.md)
|
|
458
522
|
|
|
459
|
-
|
|
523
|
+
### Proxy Configuration
|
|
460
524
|
|
|
461
|
-
|
|
525
|
+
Route API requests through your server to avoid ad blockers:
|
|
462
526
|
|
|
463
527
|
```js
|
|
464
|
-
|
|
528
|
+
proxy: {
|
|
529
|
+
baseUrl: 'https://yourdomain.com/api/proxy',
|
|
530
|
+
headers: {
|
|
531
|
+
'X-Custom-Auth': 'your-token'
|
|
532
|
+
}
|
|
533
|
+
}
|
|
465
534
|
```
|
|
466
535
|
|
|
467
|
-
|
|
536
|
+
See [`docs/PROXY.md`](docs/PROXY.md) for implementation guide.
|
|
468
537
|
|
|
469
|
-
|
|
538
|
+
### Promo Ticker
|
|
470
539
|
|
|
471
|
-
|
|
540
|
+
Display rotating promotional messages:
|
|
472
541
|
|
|
473
542
|
```js
|
|
474
|
-
|
|
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
|
-
|
|
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
|
-
|
|
578
|
+
**Identifier types:** UPC, product ID, or Salsify grouping ID
|
|
480
579
|
|
|
481
|
-
|
|
580
|
+
#### Cart
|
|
482
581
|
|
|
483
582
|
```js
|
|
484
|
-
await client.
|
|
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
|
-
|
|
591
|
+
**Use case:** Dedicated cart page
|
|
592
|
+
|
|
593
|
+
#### Checkout
|
|
594
|
+
|
|
595
|
+
```js
|
|
596
|
+
const component = await client.injectCheckoutElement('checkout-container');
|
|
488
597
|
|
|
489
|
-
|
|
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
|
-
|
|
604
|
+
**Use case:** Dedicated checkout page
|
|
492
605
|
|
|
493
|
-
|
|
606
|
+
#### Address
|
|
494
607
|
|
|
495
608
|
```js
|
|
496
|
-
client.
|
|
609
|
+
const component = await client.injectAddressElement('address-container');
|
|
497
610
|
|
|
498
|
-
//
|
|
499
|
-
|
|
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
|
-
|
|
617
|
+
**Use case:** Shipping address collection page
|
|
503
618
|
|
|
504
|
-
|
|
619
|
+
#### Access All Injected Components
|
|
505
620
|
|
|
506
621
|
```js
|
|
507
|
-
|
|
622
|
+
// Get all injected components
|
|
623
|
+
const injectedComponents = client.getInjectedComponents();
|
|
508
624
|
|
|
509
|
-
//
|
|
510
|
-
|
|
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
|
-
|
|
647
|
+
**Returns:** `Map<string, IInjectedComponent>` - Map of container IDs to component wrappers
|
|
514
648
|
|
|
515
|
-
|
|
649
|
+
**Use cases:**
|
|
650
|
+
- Debugging and inspecting injected components
|
|
651
|
+
- Bulk operations on multiple components
|
|
652
|
+
- Component management and cleanup
|
|
516
653
|
|
|
517
|
-
|
|
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.
|
|
673
|
+
client.ui.floatingCartButton(true);
|
|
521
674
|
```
|
|
522
675
|
|
|
523
|
-
|
|
676
|
+
**Parameters:**
|
|
677
|
+
- `showItemsCount` - Show item count badge (optional)
|
|
678
|
+
|
|
679
|
+
**Use case:** Always-visible cart access (bottom-right corner)
|
|
524
680
|
|
|
525
|
-
|
|
681
|
+
#### Live Cart Data Display
|
|
682
|
+
|
|
683
|
+
Bind elements to auto-update with cart data:
|
|
526
684
|
|
|
527
685
|
```js
|
|
528
|
-
|
|
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.
|
|
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.
|
|
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(
|
|
745
|
-
console.log(
|
|
746
|
-
console.log(
|
|
747
|
-
console.log(
|
|
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
|
|
766
|
-
console.log('Added to cart:',
|
|
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
|
-
|
|
771
|
-
|
|
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
|
-
##
|
|
992
|
+
## 🎨 Themes & Customization
|
|
819
993
|
|
|
820
|
-
|
|
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
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
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
|
-
###
|
|
1035
|
+
### Component-Specific Theming
|
|
833
1036
|
|
|
834
|
-
|
|
835
|
-
- **`staging`**: Pre-production testing environment
|
|
836
|
-
- **`development`**: Development environment with additional debugging
|
|
837
|
-
- **`local`**: Local development environment
|
|
1037
|
+
#### Product Component
|
|
838
1038
|
|
|
839
|
-
|
|
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
|
-
|
|
1061
|
+
#### Cart Component
|
|
842
1062
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
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
|
-
|
|
1079
|
+
#### Checkout Component
|
|
853
1080
|
|
|
854
1081
|
```js
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
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
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
1091
|
+
layout: {
|
|
1092
|
+
emailOptIn: {
|
|
1093
|
+
show: true,
|
|
1094
|
+
checked: false,
|
|
1095
|
+
text: 'Email me with news'
|
|
872
1096
|
},
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
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
|
-
|
|
1122
|
+
### Dynamic Theme Updates (Builder Mode)
|
|
1123
|
+
|
|
1124
|
+
In development with `isBuilder: true`, update themes in real-time:
|
|
895
1125
|
|
|
896
1126
|
```js
|
|
897
|
-
|
|
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
|
-
|
|
1134
|
+
theme: { primaryColor: '#ff6b6b' }
|
|
900
1135
|
});
|
|
901
1136
|
|
|
1137
|
+
// Update component-specific themes
|
|
902
1138
|
await client.builder.updateProductComponent({
|
|
903
|
-
layout: {
|
|
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
|
-
|
|
1155
|
+
**📖 For complete theming documentation:** See [`docs/THEMING.md`](docs/THEMING.md)
|
|
908
1156
|
|
|
909
|
-
|
|
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
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
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
|
-
|
|
1405
|
+
### Purchase Minimum Alerts
|
|
924
1406
|
|
|
925
|
-
|
|
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
|
-
|
|
1409
|
+
### Age Verification
|
|
928
1410
|
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
###
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
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
|
-
|
|
1582
|
+
**Token refresh:** The SDK automatically handles token expiration and refresh.
|
|
1583
|
+
|
|
1584
|
+
### Logger
|
|
963
1585
|
|
|
964
|
-
|
|
1586
|
+
Built-in logging system with configurable levels:
|
|
965
1587
|
|
|
966
|
-
|
|
1588
|
+
```js
|
|
1589
|
+
const client = await Elements('YOUR_API_KEY', {
|
|
1590
|
+
debugMode: 'console' // 'none' | 'console' | 'panel'
|
|
1591
|
+
});
|
|
967
1592
|
|
|
968
|
-
|
|
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
|
-
<!--
|
|
1798
|
+
<!-- In your theme's header.php or functions.php -->
|
|
972
1799
|
<script
|
|
973
1800
|
data-liquid-commerce-elements
|
|
974
|
-
data-token="
|
|
975
|
-
data-env="
|
|
976
|
-
|
|
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
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
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
|
-
|
|
1821
|
+
<!-- In product template -->
|
|
1822
|
+
<div data-lce-product="{{ product.barcode }}"></div>
|
|
1823
|
+
```
|
|
988
1824
|
|
|
989
|
-
###
|
|
1825
|
+
### Multi-Page Applications
|
|
990
1826
|
|
|
991
|
-
|
|
1827
|
+
For SPAs and multi-page apps, initialize once and reuse:
|
|
992
1828
|
|
|
993
|
-
```
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
enableDebugging: true,
|
|
997
|
-
customTheme: { /* theme config */ }
|
|
998
|
-
});
|
|
1829
|
+
```js
|
|
1830
|
+
// app.js (initialize once)
|
|
1831
|
+
let elementsClient = null;
|
|
999
1832
|
|
|
1000
|
-
|
|
1001
|
-
|
|
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:
|
|
1845
|
+
{ containerId: 'pdp-1', identifier: productId }
|
|
1004
1846
|
]);
|
|
1005
|
-
|
|
1847
|
+
|
|
1848
|
+
// cart-page.js
|
|
1849
|
+
const client = await getElementsClient();
|
|
1850
|
+
const cartComponent = await client.injectCartElement('cart-container');
|
|
1006
1851
|
```
|
|
1007
1852
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
- Dynamic theme updates
|
|
1853
|
+
---
|
|
1854
|
+
|
|
1855
|
+
## 🚨 Error Handling
|
|
1856
|
+
|
|
1857
|
+
### Initialization Errors
|
|
1014
1858
|
|
|
1015
|
-
|
|
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
|
-
###
|
|
1875
|
+
### Action Errors
|
|
1018
1876
|
|
|
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`)
|
|
1877
|
+
All actions emit failure events with detailed error information:
|
|
1023
1878
|
|
|
1024
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
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
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
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
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
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
|
-
|
|
1979
|
+
---
|
|
1060
1980
|
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
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
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
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
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
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
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
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
|
-
###
|
|
2073
|
+
### Defer Non-Critical Operations
|
|
1094
2074
|
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
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
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
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
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
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
|
-
###
|
|
2133
|
+
### Cache Frequently Accessed Data
|
|
1120
2134
|
|
|
1121
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1137
|
-
|
|
1138
|
-
-
|
|
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
|
-
###
|
|
2165
|
+
### Minimize Theme Complexity
|
|
1141
2166
|
|
|
1142
|
-
|
|
1143
|
-
```bash
|
|
1144
|
-
# Start development
|
|
1145
|
-
pnpm run dev
|
|
2167
|
+
Simpler themes = faster rendering:
|
|
1146
2168
|
|
|
1147
|
-
|
|
1148
|
-
|
|
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
|
-
|
|
1152
|
-
```bash
|
|
1153
|
-
# Clean and build for release
|
|
1154
|
-
pnpm run clean:hard
|
|
2191
|
+
### Monitor Performance
|
|
1155
2192
|
|
|
1156
|
-
|
|
1157
|
-
pnpm run changelog
|
|
2193
|
+
Track SDK performance in production:
|
|
1158
2194
|
|
|
1159
|
-
|
|
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
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
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
|
-
|
|
1168
|
-
|
|
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.
|