@liquidcommerce/elements-sdk 2.6.7 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/README.md +83 -2519
  2. package/dist/index.checkout.esm.js +16086 -0
  3. package/dist/index.esm.js +16267 -13788
  4. package/dist/types/auto-initialize/checkout.d.ts +2 -0
  5. package/dist/types/auto-initialize/shared-utils.d.ts +27 -0
  6. package/dist/types/{elements-base-client.d.ts → clients/base.d.ts} +11 -1
  7. package/dist/types/clients/checkout.d.ts +13 -0
  8. package/dist/types/constants/core.constant.d.ts +5 -3
  9. package/dist/types/core/api/api-client.service.d.ts +0 -2
  10. package/dist/types/core/client/actions/base-action.service.d.ts +15 -0
  11. package/dist/types/core/client/actions/client-address-action.service.d.ts +18 -0
  12. package/dist/types/core/client/actions/client-cart-action.service.d.ts +37 -0
  13. package/dist/types/core/client/actions/client-checkout-action.service.d.ts +50 -0
  14. package/dist/types/core/client/actions/client-product-action.service.d.ts +12 -0
  15. package/dist/types/core/client/client-action.service.d.ts +6 -73
  16. package/dist/types/core/client/client-config.service.d.ts +3 -4
  17. package/dist/types/core/pubsub/interfaces/checkout.interface.d.ts +1 -0
  18. package/dist/types/core/store/interfaces/core.interface.d.ts +14 -1
  19. package/dist/types/core/store/interfaces/metadata.interface.d.ts +11 -0
  20. package/dist/types/core/store/interfaces/product-list.interface.d.ts +45 -0
  21. package/dist/types/core/store/interfaces/product.interface.d.ts +1 -0
  22. package/dist/types/core/store/store.constant.d.ts +4 -0
  23. package/dist/types/enums/core.enum.d.ts +14 -1
  24. package/dist/types/enums/index.d.ts +0 -1
  25. package/dist/types/index.checkout.d.ts +7 -0
  26. package/dist/types/index.checkout.umd.d.ts +4 -0
  27. package/dist/types/index.d.ts +2 -2
  28. package/dist/types/interfaces/api/checkout.interface.d.ts +2 -1
  29. package/dist/types/interfaces/api/product-list.interface.d.ts +13 -5
  30. package/dist/types/interfaces/configs/checkout.interface.d.ts +1 -0
  31. package/dist/types/interfaces/configs/global.interface.d.ts +4 -2
  32. package/dist/types/interfaces/configs/index.d.ts +1 -0
  33. package/dist/types/interfaces/configs/product-list.interface.d.ts +28 -0
  34. package/dist/types/interfaces/core.interface.d.ts +28 -6
  35. package/dist/types/modules/address/address-input.component.d.ts +11 -0
  36. package/dist/types/modules/address/styles/register-styles.d.ts +1 -0
  37. package/dist/types/modules/cart/styles/register-styles.d.ts +1 -0
  38. package/dist/types/modules/checkout/checkout.commands.d.ts +6 -2
  39. package/dist/types/modules/checkout/checkout.component.d.ts +2 -0
  40. package/dist/types/modules/checkout/components/checkout-completed.component.d.ts +2 -0
  41. package/dist/types/modules/checkout/components/checkout-header.component.d.ts +1 -0
  42. package/dist/types/modules/checkout/styles/register-styles.d.ts +1 -0
  43. package/dist/types/modules/product/styles/register-styles.d.ts +1 -0
  44. package/dist/types/modules/product-list/components/card-components/index.d.ts +7 -0
  45. package/dist/types/modules/product-list/components/card-components/product-badge.d.ts +8 -0
  46. package/dist/types/modules/product-list/components/card-components/product-button.d.ts +11 -0
  47. package/dist/types/modules/product-list/components/card-components/product-fulfillments.d.ts +12 -0
  48. package/dist/types/modules/product-list/components/card-components/product-price-and-personalization.d.ts +13 -0
  49. package/dist/types/modules/product-list/components/card-components/product-quantity-selector.d.ts +10 -0
  50. package/dist/types/modules/product-list/components/card-components/product-sizes-list.d.ts +9 -0
  51. package/dist/types/modules/product-list/components/card-components/product-title.d.ts +6 -0
  52. package/dist/types/modules/product-list/components/filter-components/index.d.ts +7 -0
  53. package/dist/types/modules/product-list/components/filter-components/product-list-apply-filter-button.d.ts +1 -0
  54. package/dist/types/modules/product-list/components/filter-components/product-list-chip.d.ts +5 -0
  55. package/dist/types/modules/product-list/components/filter-components/product-list-filters-chips.d.ts +13 -0
  56. package/dist/types/modules/product-list/components/filter-components/product-list-fulfillment-filter.d.ts +14 -0
  57. package/dist/types/modules/product-list/components/{product-list-filters-subcomponents/product-list-price-filter.components.d.ts → filter-components/product-list-price-filter.d.ts} +1 -1
  58. package/dist/types/modules/product-list/components/filter-components/product-list-toggle-filters.d.ts +13 -0
  59. package/dist/types/modules/product-list/components/index.d.ts +7 -3
  60. package/dist/types/modules/product-list/components/product-list-card-loading.component.d.ts +2 -1
  61. package/dist/types/modules/product-list/components/product-list-engraving.component.d.ts +10 -0
  62. package/dist/types/modules/product-list/components/product-list-filters.component.d.ts +58 -37
  63. package/dist/types/modules/product-list/components/product-list-product-pre-cart.component.d.ts +28 -0
  64. package/dist/types/modules/product-list/components/product-list-retailers.component.d.ts +26 -0
  65. package/dist/types/modules/product-list/components/product-list-search.component.d.ts +22 -0
  66. package/dist/types/modules/product-list/product-list-card.component.d.ts +30 -0
  67. package/dist/types/modules/product-list/product-list.commands.d.ts +62 -3
  68. package/dist/types/modules/product-list/product-list.component.d.ts +16 -43
  69. package/dist/types/{enums/cloud.enum.d.ts → modules/product-list/product-list.constants.d.ts} +20 -1
  70. package/dist/types/modules/product-list/product-list.interface.d.ts +33 -24
  71. package/dist/types/modules/product-list/styles/product-list-card.style.d.ts +1 -0
  72. package/dist/types/modules/product-list/styles/product-list-filters.style.d.ts +1 -0
  73. package/dist/types/modules/product-list/styles/register-styles.d.ts +1 -0
  74. package/dist/types/modules/theme-provider/constants/component-groupings.d.ts +1 -0
  75. package/dist/types/modules/theme-provider/constants/css-variable-mappings.d.ts +1 -1
  76. package/dist/types/modules/theme-provider/services/style-registry.service.d.ts +16 -0
  77. package/dist/types/modules/theme-provider/services/stylesheet-generator.service.d.ts +0 -1
  78. package/dist/types/modules/theme-provider/styles/register-styles.d.ts +1 -0
  79. package/dist/types/modules/theme-provider/theme-provider.service.d.ts +2 -1
  80. package/dist/types/modules/ui-components/engraving/engraving-form.component.d.ts +13 -1
  81. package/dist/types/modules/ui-components/input/index.d.ts +0 -1
  82. package/dist/types/modules/ui-components/input/input.component.d.ts +8 -1
  83. package/dist/types/modules/ui-components/modal/modal.component.d.ts +23 -0
  84. package/dist/types/modules/ui-components/styles/modal.style.d.ts +1 -0
  85. package/dist/types/modules/ui-components/ui.commands.d.ts +3 -1
  86. package/dist/types/static/icon/check.icon.d.ts +2 -0
  87. package/dist/types/static/icon/index.d.ts +1 -0
  88. package/docs/gitbook/actions.md +160 -0
  89. package/docs/gitbook/address.md +48 -0
  90. package/docs/gitbook/cart.md +65 -0
  91. package/docs/gitbook/checkout.md +131 -0
  92. package/docs/gitbook/events.md +137 -0
  93. package/docs/gitbook/overview.md +166 -0
  94. package/docs/gitbook/product.md +64 -0
  95. package/docs/gitbook/quick-start-guide.md +393 -0
  96. package/docs/v1/README.md +210 -0
  97. package/docs/v1/api/actions/address-actions.md +281 -0
  98. package/docs/v1/api/actions/cart-actions.md +337 -0
  99. package/docs/v1/api/actions/checkout-actions.md +387 -0
  100. package/docs/v1/api/actions/product-actions.md +115 -0
  101. package/docs/v1/api/client.md +482 -0
  102. package/docs/v1/api/configuration.md +1 -0
  103. package/docs/v1/api/injection-methods.md +247 -0
  104. package/docs/v1/api/typescript-types.md +1 -0
  105. package/docs/v1/api/ui-helpers.md +200 -0
  106. package/docs/v1/examples/advanced-patterns.md +96 -0
  107. package/docs/v1/examples/checkout-flow.md +91 -0
  108. package/docs/v1/examples/custom-theming.md +63 -0
  109. package/docs/v1/examples/multi-product-page.md +90 -0
  110. package/docs/v1/examples/simple-product-page.md +89 -0
  111. package/docs/v1/getting-started/concepts.md +507 -0
  112. package/docs/v1/getting-started/installation.md +328 -0
  113. package/docs/v1/getting-started/quick-start.md +405 -0
  114. package/docs/v1/guides/address-component.md +431 -0
  115. package/docs/v1/guides/best-practices.md +324 -0
  116. package/docs/v1/guides/cart-component.md +737 -0
  117. package/docs/v1/guides/checkout-component.md +672 -0
  118. package/docs/v1/guides/events.md +191 -0
  119. package/docs/v1/guides/product-component.md +686 -0
  120. package/docs/v1/guides/product-list-component.md +598 -0
  121. package/docs/v1/guides/theming.md +216 -0
  122. package/docs/v1/integration/angular.md +39 -0
  123. package/docs/v1/integration/laravel.md +41 -0
  124. package/docs/v1/integration/nextjs.md +60 -0
  125. package/docs/v1/integration/proxy-setup.md +89 -0
  126. package/docs/v1/integration/react.md +64 -0
  127. package/docs/v1/integration/vanilla-js.md +84 -0
  128. package/docs/v1/integration/vue.md +34 -0
  129. package/docs/v1/reference/browser-support.md +35 -0
  130. package/docs/v1/reference/error-handling.md +70 -0
  131. package/docs/v1/reference/performance.md +54 -0
  132. package/docs/v1/reference/troubleshooting.md +64 -0
  133. package/package.json +19 -12
  134. package/dist/types/modules/product-list/components/product-list-card.component.d.ts +0 -37
  135. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/index.d.ts +0 -6
  136. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/product-list-apply-filter-button.component.d.ts +0 -1
  137. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/product-list-delivery-options-filter.components.d.ts +0 -16
  138. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/product-list-search.component.d.ts +0 -16
  139. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/product-list-toggle-filters.components.d.ts +0 -18
  140. package/dist/types/modules/theme-provider/styles/address/index.d.ts +0 -1
  141. package/dist/types/modules/theme-provider/styles/cart/index.d.ts +0 -1
  142. package/dist/types/modules/theme-provider/styles/checkout/index.d.ts +0 -1
  143. package/dist/types/modules/theme-provider/styles/product/index.d.ts +0 -3
  144. package/dist/types/modules/theme-provider/styles/product-list/index.d.ts +0 -1
  145. package/dist/types/modules/theme-provider/styles/ui/index.d.ts +0 -3
  146. package/dist/types/modules/ui-components/input/birthdate-input.component.d.ts +0 -53
  147. package/docs/ACTIONS.md +0 -1300
  148. package/docs/BROWSER_SUPPORT.md +0 -279
  149. package/docs/CONFIGURATION.md +0 -853
  150. package/docs/DOCUMENTATION_INDEX.md +0 -311
  151. package/docs/EVENTS.md +0 -798
  152. package/docs/PROXY.md +0 -228
  153. package/docs/THEMING.md +0 -592
  154. package/docs/TROUBLESHOOTING.md +0 -793
  155. package/umd/elements.js +0 -1
  156. /package/dist/types/{auto-initialize.d.ts → auto-initialize/main.d.ts} +0 -0
  157. /package/dist/types/{elements-builder-client.d.ts → clients/builder.d.ts} +0 -0
  158. /package/dist/types/{elements-client-helper.d.ts → clients/helpers.d.ts} +0 -0
  159. /package/dist/types/{elements-client.d.ts → clients/main.d.ts} +0 -0
  160. /package/dist/types/modules/{theme-provider/styles/address → address/styles}/address.style.d.ts +0 -0
  161. /package/dist/types/modules/{theme-provider/styles/cart → cart/styles}/cart.style.d.ts +0 -0
  162. /package/dist/types/modules/{theme-provider/styles/checkout → checkout/styles}/checkout.style.d.ts +0 -0
  163. /package/dist/types/modules/{theme-provider/styles/product → product/styles}/image-carousel.style.d.ts +0 -0
  164. /package/dist/types/modules/{theme-provider/styles/product → product/styles}/product.style.d.ts +0 -0
  165. /package/dist/types/modules/{theme-provider/styles/product → product/styles}/retailers.style.d.ts +0 -0
  166. /package/dist/types/modules/product-list/components/{product-list-filters-subcomponents/product-list-checkbox-filter.components.d.ts → filter-components/product-list-checkbox-filter.d.ts} +0 -0
  167. /package/dist/types/modules/{theme-provider/styles/product-list → product-list/styles}/product-list.style.d.ts +0 -0
  168. /package/dist/types/modules/{theme-provider/styles/ui → ui-components/styles}/drawer.style.d.ts +0 -0
  169. /package/dist/types/modules/{theme-provider/styles/ui → ui-components/styles}/loading.style.d.ts +0 -0
  170. /package/dist/types/modules/{theme-provider/styles/ui → ui-components/styles}/promo-code-ticker.style.d.ts +0 -0
package/README.md CHANGED
@@ -9,2582 +9,146 @@ Elements SDK
9
9
 
10
10
  [![JavaScript](https://img.shields.io/badge/JavaScript-ES6+-F7DF1E?style=for-the-badge&logo=javascript&logoColor=black)](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
11
11
  [![TypeScript](https://img.shields.io/badge/TypeScript-5+-3178C6?style=for-the-badge&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
12
- [![npm](https://img.shields.io/badge/npm-10+-CB3837?style=for-the-badge&logo=npm&logoColor=white)](https://www.npmjs.com/)
13
- [![pnpm](https://img.shields.io/badge/pnpm-8+-F69220?style=for-the-badge&logo=pnpm&logoColor=white)](https://pnpm.io/)
14
- [![Rollup](https://img.shields.io/badge/Rollup-4+-EC4A3F?style=for-the-badge&logo=rollup.js&logoColor=white)](https://rollupjs.org/)
15
-
16
- [![License: UNLICENSED](https://img.shields.io/badge/License-UNLICENSED-red.svg)](LICENSE)
17
- [![Bundle Size](https://img.shields.io/badge/Bundle%20Size-~150KB-blue)](./umd)
18
- [![Zero Dependencies](https://img.shields.io/badge/Dependencies-Zero-brightgreen)](./package.json)
19
- [![Browser Support](https://img.shields.io/badge/Browsers-2018+-4285F4?logo=googlechrome&logoColor=white)](./docs/BROWSER_SUPPORT.md)
20
-
21
- **Add product, cart, and checkout experiences to any website with a few lines of code**
22
-
23
- </div>
24
-
25
- ## 📋 Table of Contents
26
-
27
- <details>
28
- <summary>Click to expand</summary>
29
-
30
- - [Overview](#-overview)
31
- - [Quick Start](#-quick-start)
32
- - [Advanced Usage](#-advanced-usage)
33
- - [Browser Support](#-browser-support)
34
- - [Configuration](#-configuration)
35
- - [SDK Methods & API](#-sdk-methods--api)
36
- - [Actions](#-actions)
37
- - [Events](#-events)
38
- - [Themes & Customization](#-themes--customization)
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)
44
- - [Proxy Configuration](#-proxy-configuration)
45
- - [Documentation](#-documentation)
46
- - [Versioning](#-versioning)
47
- - [Support](#-support)
48
-
49
- </details>
50
-
51
- ## 🎯 Overview
52
-
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.
54
-
55
- ### ✨ Key Features
56
-
57
- <table>
58
- <tr>
59
- <td width="50%">
60
-
61
- **🚀 Quick Integration**
62
- - Auto-initialization with data attributes
63
- - Zero configuration setup
64
- - CDN or NPM installation
65
- - Works with any framework or vanilla JS
66
-
67
- </td>
68
- <td width="50%">
69
-
70
- **🛍️ Complete E-commerce**
71
- - Product display components
72
- - Shopping cart with real-time updates
73
- - Full checkout flow
74
- - Address management
75
-
76
- </td>
77
- </tr>
78
- <tr>
79
- <td width="50%">
80
-
81
- **🎨 Customizable UI**
82
- - Comprehensive theme system
83
- - Component-level styling
84
- - Responsive design
85
- - Modern, accessible components
86
-
87
- </td>
88
- <td width="50%">
89
-
90
- **⚡ Performance First**
91
- - ~150KB bundle size
92
- - Zero runtime dependencies
93
- - Lazy loading support
94
- - Optimized for Core Web Vitals
95
-
96
- </td>
97
- </tr>
98
- </table>
99
-
100
- ## 🚀 Quick Start
101
-
102
- The fastest way to add e-commerce to your site is with **auto-initialization** - a single script tag that does everything.
103
-
104
- ### The Simplest Setup (30 seconds)
105
-
106
- Add this single script tag to your page:
107
-
108
- ```html
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>
115
- ```
116
-
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
122
-
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>
145
- ```
146
-
147
- **Use case:** Static HTML pages with known products
148
-
149
- #### Method 2: JSON Configuration (Best for CMS/dynamic content)
150
-
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>
170
- ```
171
-
172
- **Use case:** CMS platforms, templating engines, server-side rendering
173
-
174
- #### Method 3: Annotated Elements (Best for grids/lists)
175
-
176
- Mark any div with a data attribute:
177
-
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>
184
-
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
- ```
192
-
193
- **Use case:** Product grids, category pages, search results
194
-
195
- ### Adding a Product List
196
-
197
- Display a filtered, paginated product catalog with infinite scroll. Perfect for category pages, catalog pages, and search results.
198
-
199
- Add a product list to any page with a data attribute:
200
-
201
- ```html
202
- <div data-liquid-commerce-elements-products-list
203
- data-card="standard"
204
- data-rows="3"
205
- data-columns="4"
206
- data-filters="personalization,pre-order,delivery-options"
207
- data-product-url="/product/{upc}">
208
- </div>
209
-
210
- <script
211
- data-liquid-commerce-elements
212
- data-token="YOUR_API_KEY"
213
- data-env="production"
214
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
215
- ></script>
216
- ```
217
-
218
- **Attributes:**
219
- - `data-liquid-commerce-elements-products-list` - Enables product list on this div
220
- - `data-card` - Card variant: `standard` (default)
221
- - `data-rows` - Number of rows per page (default: `3`)
222
- - `data-columns` - Number of columns (default: `4`)
223
- - `data-card-fill` - Makes cards fill available space (optional flag)
224
- - `data-filters` - Comma-separated filters: `personalization`, `pre-order`, `delivery-options`
225
- - `data-product-url` - Product URL template with `{upc}` or `{grouping}` placeholder
226
-
227
- **Use case:** Category pages, catalog pages, search results, filtered product browsing
228
-
229
- ### Customizing the Cart Button
230
-
231
- By default, you get a floating cart button with badge. Here's how to customize it:
232
-
233
- #### Option 1: Cart Button in a Specific Container
234
-
235
- ```html
236
- <nav>
237
- <div id="header-cart"></div>
238
- </nav>
239
-
240
- <script
241
- data-liquid-commerce-elements
242
- data-token="YOUR_API_KEY"
243
- data-env="production"
244
- data-cart-badge-button="header-cart"
245
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
246
- ></script>
247
- ```
248
-
249
- **Position Options:**
250
-
251
- You can control where the cart button is placed relative to a target element:
252
-
253
- ```html
254
- <!-- Place inside the target (default) -->
255
- <script data-cart-badge-button="header-cart" ...></script>
256
-
257
- <!-- Place above the target -->
258
- <script data-cart-badge-button="above:.header-logo" ...></script>
259
-
260
- <!-- Place below the target -->
261
- <script data-cart-badge-button="below:#main-nav" ...></script>
262
-
263
- <!-- Replace the target -->
264
- <script data-cart-badge-button="replace:.old-cart" ...></script>
265
- ```
266
-
267
- **ID Auto-Prefixing:**
268
-
269
- Element IDs are automatically prefixed with `#` if needed:
270
-
271
- ```html
272
- <!-- These are equivalent: -->
273
- <script data-cart-button="header-cart" ...></script>
274
- <script data-cart-button="#header-cart" ...></script>
275
- ```
276
-
277
- #### Option 2: Floating Cart Button (Default)
278
-
279
- If no cart button attribute is provided, or if the target element is not found, the SDK automatically falls back to a floating cart button (bottom-right corner):
280
-
281
- ```html
282
- <!-- Empty attribute = floating cart button without badge -->
283
- <script data-cart-button="" ...></script>
284
-
285
- <!-- Empty badge attribute = floating cart button with badge -->
286
- <script data-cart-badge-button="" ...></script>
287
-
288
- <!-- Or simply omit the attribute for floating button with badge -->
289
- <script
290
- data-liquid-commerce-elements
291
- data-token="YOUR_API_KEY"
292
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
293
- ></script>
294
- ```
295
-
296
- #### Option 3: No Cart Button (Manual Control)
297
-
298
- Hide the cart button completely when you want to manage cart access manually:
299
-
300
- ```html
301
- <script
302
- data-liquid-commerce-elements
303
- data-token="YOUR_API_KEY"
304
- data-env="production"
305
- data-cart-button-hidden
306
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
307
- ></script>
308
- ```
309
-
310
- **Use case:** When you have a custom cart implementation or want to trigger cart display programmatically using `client.actions.cart.openCart()`
311
-
312
- ### Advanced Auto-Init Features
313
-
314
- #### Add Product via URL (Marketing Links)
315
-
316
- Enable "add to cart" via URL parameters for email campaigns and ads:
317
-
318
- ```html
319
- <script
320
- data-liquid-commerce-elements
321
- data-token="YOUR_API_KEY"
322
- data-env="production"
323
- data-product-param="lce_product"
324
- data-product-fulfillment-type-param="lce_fulfillment"
325
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
326
- ></script>
327
- ```
328
-
329
- Now this URL auto-adds a product to cart:
330
- ```
331
- https://yoursite.com/shop?lce_product=00619947000020&lce_fulfillment=shipping
332
- ```
333
-
334
- **Use case:** Email campaigns, social media ads, QR codes
335
-
336
- #### Apply Promo Code via URL (Campaign Tracking)
337
-
338
- Auto-apply promo codes from URL parameters:
339
-
340
- ```html
341
- <script
342
- data-liquid-commerce-elements
343
- data-token="YOUR_API_KEY"
344
- data-env="production"
345
- data-promo-code-param="lce_promo"
346
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
347
- ></script>
348
- ```
349
-
350
- Now this URL auto-applies a promo code:
351
- ```
352
- https://yoursite.com/shop?lce_promo=SUMMER20
353
- ```
354
-
355
- **Use case:** Promotional campaigns, influencer codes, affiliate links
356
-
357
- #### Promo Ticker (Rotating Promotions)
358
-
359
- Display rotating promotional messages:
360
-
361
- ```html
362
- <script
363
- data-liquid-commerce-elements
364
- data-token="YOUR_API_KEY"
365
- data-env="production"
366
- data-promo-code="FREESHIP"
367
- data-promo-text="Free Shipping Today Only!|Use code FREESHIP at checkout"
368
- data-promo-separator="•"
369
- data-promo-active-from="2025-01-01T00:00:00Z"
370
- data-promo-active-until="2025-01-31T23:59:59Z"
371
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
372
- ></script>
373
- ```
374
-
375
- **Use case:** Time-sensitive promotions, holiday sales, flash deals
376
-
377
- #### Debug Mode (Development)
378
-
379
- Enable debug logging during development:
380
-
381
- ```html
382
- <script
383
- data-liquid-commerce-elements
384
- data-token="YOUR_API_KEY"
385
- data-env="development"
386
- data-debug-mode="console"
387
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
388
- ></script>
389
- ```
390
-
391
- **Debug modes:**
392
- - `console` - Logs to browser console
393
- - `panel` - Shows visual debug panel + console logs
394
- - Not set - No debugging (production default)
395
-
396
- ### Complete Auto-Init Reference
397
-
398
- Here's every available data attribute:
399
-
400
- ```html
401
- <script
402
- data-liquid-commerce-elements
403
-
404
- <!-- Required -->
405
- data-token="YOUR_API_KEY"
406
-
407
- <!-- Environment -->
408
- data-env="production|staging|development|local"
409
-
410
- <!-- Cart Button -->
411
- data-cart-button="container-id" <!-- Simple cart button (no badge) -->
412
- data-cart-badge-button="container-id" <!-- Cart button with badge -->
413
- data-cart-button-hidden <!-- Hide cart button completely -->
414
-
415
- <!-- Cart Button with Position Prefixes -->
416
- data-cart-button="above:.logo" <!-- Place above target -->
417
- data-cart-badge-button="below:#header" <!-- Place below target -->
418
- data-cart-button="inside:.nav" <!-- Place inside target (default) -->
419
- data-cart-badge-button="replace:.old-cart" <!-- Replace target -->
420
-
421
- <!-- Cart Button Floating (empty values) -->
422
- data-cart-button="" <!-- Floating button without badge -->
423
- data-cart-badge-button="" <!-- Floating button with badge -->
424
-
425
- <!-- Products (Method 1: Direct) -->
426
- data-container-1="div-id"
427
- data-product-1="identifier"
428
- data-container-2="div-id"
429
- data-product-2="identifier"
430
-
431
- <!-- Product List -->
432
- <div data-liquid-commerce-elements-products-list
433
- data-card="standard"
434
- data-rows="3"
435
- data-columns="4"
436
- data-card-fill
437
- data-filters="personalization,pre-order,delivery-options"
438
- data-product-url="/product/{upc}">
439
- </div>
440
-
441
- <!-- URL Parameters -->
442
- data-product-param="lce_product"
443
- data-product-fulfillment-type-param="lce_fulfillment"
444
- data-promo-code-param="lce_promo"
445
-
446
- <!-- Promo Ticker -->
447
- data-promo-code="CODE"
448
- data-promo-text="Message 1|Message 2"
449
- data-promo-separator="•"
450
- data-promo-active-from="2025-01-01T00:00:00Z"
451
- data-promo-active-until="2025-12-31T23:59:59Z"
452
-
453
- <!-- Debugging (dev only) -->
454
- data-debug-mode="console|panel"
455
-
456
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
457
- ></script>
458
- ```
459
-
460
- **📖 For complete auto-init options:** See [`docs/CONFIGURATION.md`](docs/CONFIGURATION.md) for all data attributes and configuration details.
461
-
462
- ---
463
-
464
- ## 🔧 Advanced Usage
465
-
466
- Need more control? Initialize programmatically for full access to the SDK API.
467
-
468
- ### Installation
469
-
470
- **CDN:**
471
- ```html
472
- <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
473
-
474
- <!-- Pin to specific version: -->
475
- <script src="https://assets-elements.liquidcommerce.us/all/1.2.3/elements.js"></script>
476
- ```
477
-
478
- **NPM:**
479
- ```bash
480
- npm install @liquidcommerce/elements-sdk
481
- # or
482
- pnpm add @liquidcommerce/elements-sdk
483
- ```
484
-
485
- ### Programmatic Initialization
486
-
487
- ```html
488
- <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
489
- <script>
490
- (async () => {
491
- const client = await window.Elements('YOUR_API_KEY', {
492
- env: 'production',
493
- debugMode: 'none',
494
- customTheme: { /* theming overrides */ },
495
- proxy: { /* proxy config */ }
496
- });
497
-
498
- // Inject components
499
- const components = await client.injectProductElement([
500
- { containerId: 'pdp-1', identifier: '00619947000020' }
501
- ]);
502
-
503
- // Create cart button
504
- client.ui.cartButton('cart-container', true);
505
-
506
- // Use actions API
507
- await client.actions.cart.addProduct([{
508
- identifier: '00619947000020',
509
- fulfillmentType: 'shipping',
510
- quantity: 1
511
- }]);
512
- })();
513
- </script>
514
- ```
515
-
516
- **NPM Import:**
517
- ```js
518
- import { Elements } from '@liquidcommerce/elements-sdk';
519
-
520
- const client = await Elements('YOUR_API_KEY', { env: 'production' });
521
- ```
522
-
523
- ---
524
-
525
- ## 🌐 Browser Support
526
-
527
- ⚠️ **Important**: This SDK is designed for browser environments only. It will not work in server-side rendering, Node.js, or other non-browser environments.
528
-
529
- ### Supported Browsers (2018+)
530
-
531
- | Browser | Minimum Version | Released |
532
- |---------|----------------|----------|
533
- | Chrome | 66+ | April 2018 |
534
- | Firefox | 60+ | May 2018 |
535
- | Safari | 12+ | September 2018 |
536
- | Edge | 79+ (Chromium) | January 2020 |
537
- | Samsung Internet | 7.2+ | June 2018 |
538
-
539
- 📖 See [`docs/BROWSER_SUPPORT.md`](docs/BROWSER_SUPPORT.md) for detailed compatibility.
540
-
541
- ## ⚙️ Configuration
542
-
543
- ### Basic Configuration
544
-
545
- ```js
546
- const client = await Elements('YOUR_API_KEY', {
547
- env: 'production', // Environment
548
- debugMode: 'none', // Debug mode
549
- customTheme: { }, // Theme overrides
550
- proxy: { }, // Proxy configuration
551
- promoTicker: [ ] // Promotional messages
552
- });
553
- ```
554
-
555
- ### Environment Options
556
-
557
- ```js
558
- env: 'production' // Live environment (default)
559
- env: 'staging' // Pre-production testing
560
- env: 'development' // Development with extra logging
561
- env: 'local' // Local development
562
- ```
563
-
564
- ### Debug Modes
565
-
566
- ```js
567
- debugMode: 'none' // No debugging (production default)
568
- debugMode: 'console' // Console logs only
569
- debugMode: 'panel' // Visual debug panel + console logs
570
- ```
571
-
572
- **Note:** Debug mode is automatically disabled in production environment for security.
573
-
574
- ### Custom Theme
575
-
576
- Override default styles and layouts:
577
-
578
- ```js
579
- customTheme: {
580
- global: {
581
- theme: {
582
- primaryColor: '#007bff',
583
- accentColor: '#6c757d',
584
- successColor: '#28a745',
585
- errorColor: '#dc3545',
586
- buttonCornerRadius: '8px',
587
- cardCornerRadius: '12px',
588
- headingFont: {
589
- name: 'Inter',
590
- weights: [600, 700]
591
- },
592
- paragraphFont: {
593
- name: 'Inter',
594
- weights: [400, 500]
595
- }
596
- },
597
- layout: {
598
- allowPromoCodes: true,
599
- inputFieldStyle: 'outlined'
600
- }
601
- },
602
- product: {
603
- layout: {
604
- showDescription: true,
605
- addToCartButtonText: 'Add to Cart',
606
- fulfillmentDisplay: 'carousel'
607
- }
608
- },
609
- cart: {
610
- layout: {
611
- showQuantityCounter: true,
612
- drawerHeaderText: 'Your Cart'
613
- }
614
- },
615
- checkout: {
616
- layout: {
617
- allowGiftCards: true,
618
- emailOptIn: { show: true, checked: false, text: 'Email me with news' },
619
- smsOptIn: { show: true, checked: false, text: 'Text me with updates' }
620
- }
621
- }
622
- }
623
- ```
624
-
625
- **📖 For complete theming options:** See [`docs/THEMING.md`](docs/THEMING.md)
626
-
627
- ### Proxy Configuration
628
-
629
- Route API requests through your server to avoid ad blockers:
630
-
631
- ```js
632
- proxy: {
633
- baseUrl: 'https://yourdomain.com/api/proxy',
634
- headers: {
635
- 'X-Custom-Auth': 'your-token'
636
- }
637
- }
638
- ```
639
-
640
- See [`docs/PROXY.md`](docs/PROXY.md) for implementation guide.
641
-
642
- ### Promo Ticker
643
-
644
- Display rotating promotional messages:
645
-
646
- ```js
647
- promoTicker: [
648
- {
649
- promoCode: 'FREESHIP',
650
- text: ['Free Shipping Today!', 'Use code FREESHIP'],
651
- separator: '•',
652
- activeFrom: '2025-01-01T00:00:00Z',
653
- activeUntil: '2025-12-31T23:59:59Z'
654
- }
655
- ]
656
- ```
657
-
658
- **📖 For all configuration options:** See [`docs/CONFIGURATION.md`](docs/CONFIGURATION.md) for complete reference with TypeScript types.
659
-
660
- ---
661
-
662
- ## 📖 SDK Methods & API
663
-
664
- ### Component Injection
665
-
666
- Inject SDK components into your page containers. All injection methods return wrapper objects that provide component control.
667
-
668
- #### Products
669
-
670
- ```js
671
- const components = await client.injectProductElement([
672
- { containerId: 'pdp-1', identifier: '00619947000020' },
673
- { containerId: 'pdp-2', identifier: '00832889005513' }
674
- ]);
675
-
676
- // Returns: IInjectedComponent[] - Array of component wrappers
677
- // components[0].rerender() - Rerender the first component
678
- // components[0].getElement() - Get the container element
679
- // components[0].getType() - Get component type
680
- ```
681
-
682
- **Identifier types:** UPC, product ID, or Salsify grouping ID
683
-
684
- #### Cart
685
-
686
- ```js
687
- const component = await client.injectCartElement('cart-container');
688
-
689
- // Returns: IInjectedComponent | null - Component wrapper or null if failed
690
- // component.rerender() - Rerender the component
691
- // component.getElement() - Get the container element
692
- // component.getType() - Get component type
693
- ```
694
-
695
- **Use case:** Dedicated cart page
696
-
697
- #### Checkout
698
-
699
- ```js
700
- const component = await client.injectCheckoutElement('checkout-container');
701
-
702
- // Returns: IInjectedComponent | null - Component wrapper or null if failed
703
- // component.rerender() - Rerender the component
704
- // component.getElement() - Get the container element
705
- // component.getType() - Get component type
706
- ```
707
-
708
- **Use case:** Dedicated checkout page
709
-
710
- #### Address
711
-
712
- ```js
713
- const component = await client.injectAddressElement('address-container');
714
-
715
- // Returns: IInjectedComponent | null - Component wrapper or null if failed
716
- // component.rerender() - Rerender the component
717
- // component.getElement() - Get the container element
718
- // component.getType() - Get component type
719
- ```
720
-
721
- **Use case:** Shipping address collection page
722
-
723
- #### Product List
724
-
725
- ```js
726
- await client.injectProductList({
727
- containerId: 'product-list-container',
728
- rows: 3, // Number of rows per page
729
- columns: 4, // Number of columns
730
- cardVariant: 'standard', // Card style variant
731
- fillCard: false, // Fill card to available space
732
- filters: [ // Optional filters
733
- 'personalization', // Show personalized products
734
- 'pre-order', // Show pre-order products
735
- 'delivery-options' // Show delivery type filters
736
- ],
737
- productUrl: '/product/{upc}' // Optional: Product detail page URL template
738
- });
739
- ```
740
-
741
- **Parameters:**
742
- - `containerId` - Where to inject the product list
743
- - `rows` - Number of rows to display per page (default: `3`)
744
- - `columns` - Number of columns in the grid (default: `4`)
745
- - `cardVariant` - Card display style: `'standard'` (default)
746
- - `fillCard` - Whether cards should fill available space (default: `false`)
747
- - `filters` - Array of filter types to enable: `'personalization'`, `'pre-order'`, `'delivery-options'`
748
- - `productUrl` - Optional URL template for product links. Use `{upc}` or `{grouping}` placeholder
749
-
750
- **Features:**
751
- - ✅ Infinite scroll pagination
752
- - ✅ Filter by personalization, pre-order, delivery options
753
- - ✅ Address-aware (reloads when address changes)
754
- - ✅ Loading states and error handling
755
- - ✅ Automatic GTM tracking (`view_item_list`, `select_item`)
756
- - ✅ Add to cart directly from cards
757
- - ✅ Product links with tracking
758
-
759
- **Use case:** Category pages, catalog pages, search results, filtered product browsing
760
-
761
- **Note:** The product list automatically reloads when the address changes to show availability for the new location.
762
-
763
- #### Access All Injected Components
764
-
765
- ```js
766
- // Get all injected components
767
- const injectedComponents = client.getInjectedComponents();
768
-
769
- // Access specific components by container ID
770
- const productComponent = injectedComponents.get('product-container-1');
771
- const cartComponent = injectedComponents.get('cart-container');
772
-
773
- // Iterate through all components
774
- injectedComponents.forEach((component, containerId) => {
775
- console.log(`Container: ${containerId}, Type: ${component.getType()}`);
776
-
777
- // Rerender specific components
778
- if (component.getType() === 'product') {
779
- component.rerender();
780
- }
781
- });
782
-
783
- // Get all components of a specific type
784
- const productComponents = Array.from(injectedComponents.values())
785
- .filter(component => component.getType() === 'product');
786
-
787
- // Rerender all components of a type
788
- productComponents.forEach(component => component.rerender());
789
- ```
790
-
791
- **Returns:** `Map<string, IInjectedComponent>` - Map of container IDs to component wrappers
792
-
793
- **Use cases:**
794
- - Debugging and inspecting injected components
795
- - Bulk operations on multiple components
796
- - Component management and cleanup
797
-
798
- ### UI Helpers
799
-
800
- Create standalone UI elements that integrate with the SDK.
801
-
802
- #### Cart Button (in container)
803
-
804
- ```js
805
- client.ui.cartButton('header-cart', true);
806
- ```
807
-
808
- **Parameters:**
809
- - `containerId` - Where to place the button
810
- - `showItemsCount` - Show item count badge (optional)
811
-
812
- **Use case:** Header navigation, sidebar
813
-
814
- #### Floating Cart Button
815
-
816
- ```js
817
- client.ui.floatingCartButton(true);
818
- ```
819
-
820
- **Parameters:**
821
- - `showItemsCount` - Show item count badge (optional)
822
-
823
- **Use case:** Always-visible cart access (bottom-right corner)
824
-
825
- #### Live Cart Data Display
826
-
827
- Bind elements to auto-update with cart data:
828
-
829
- ```js
830
- // Show live subtotal
831
- client.ui.cartSubtotal('cart-total-display');
832
-
833
- // Show live item count (default behavior: hides when count is 0)
834
- client.ui.cartItemsCount('cart-badge');
835
-
836
- // Show live item count (always visible, even when 0)
837
- client.ui.cartItemsCount('cart-badge', { hideZero: false });
838
- ```
839
-
840
- **Parameters for `cartItemsCount`:**
841
- - `elementId` (string) - ID of the element to update
842
- - `options` (object, optional) - Configuration options:
843
- - `hideZero` (boolean, default: `true`) - When `true`, element is hidden when cart count is 0. When `false`, element remains visible showing "0".
844
-
845
- **Example:**
846
- ```html
847
- <nav>
848
- <span>Cart: $<span id="cart-total-display">0.00</span></span>
849
- <span>(<span id="cart-badge">0</span> items)</span>
850
- </nav>
851
-
852
- <script>
853
- // Default behavior - badge hidden when cart is empty
854
- client.ui.cartItemsCount('cart-badge');
855
-
856
- // Always show count, even when 0
857
- client.ui.cartItemsCount('cart-badge', { hideZero: false });
858
- </script>
859
- ```
860
-
861
- ### Builder Methods (Development Mode)
862
-
863
- When `isBuilder: true` is set, additional methods are available for theme customization:
864
-
865
- ```js
866
- const client = await Elements('YOUR_API_KEY', {
867
- env: 'development',
868
- isBuilder: true
869
- });
870
-
871
- // Update component themes
872
- await client.builder.updateComponentGlobalConfigs(globalTheme);
873
- await client.builder.updateProductComponent(productTheme);
874
- client.builder.updateCartComponent(cartTheme);
875
- client.builder.updateCheckoutComponent(checkoutTheme);
876
- client.builder.updateAddressComponent(addressTheme);
877
-
878
- // Builder injection methods (same as regular methods)
879
- const components = await client.builder.injectProductElement(params);
880
- const component = await client.builder.injectCartElement(containerId);
881
- const checkoutComponent = await client.builder.injectCheckoutElement(containerId);
882
- const addressComponent = await client.builder.injectAddressElement(containerId);
883
-
884
- // All return IInjectedComponent wrapper objects with rerender(), getElement(), getType() methods
885
- ```
886
-
887
- ## 🎬 Actions
888
-
889
- Actions provide programmatic control over SDK components. Access them via `client.actions` or `window.elements.actions`:
890
-
891
- ```js
892
- // Available after client initialization
893
- const actions = client.actions;
894
- // OR globally
895
- const actions = window.elements.actions;
896
- ```
897
-
898
- ### Product Actions
899
-
900
- ```js
901
- // Get product details
902
- const product = actions.product.getDetails('product-123');
903
- console.log(product.name, product.brand, product.region, product.variety);
904
- console.log(product.priceInfo, product.description, product.tastingNotes);
905
- ```
906
-
907
- ### Address Actions
908
-
909
- ```js
910
- // Set address using Google Places ID
911
- await actions.address.setAddressByPlacesId('ChIJ0SRjyK5ZwokRp1TwT8dJSv8');
912
-
913
- // Set address manually without Google Places (perfect for custom address forms)
914
- await actions.address.setAddressManually(
915
- {
916
- one: '123 Main St',
917
- two: 'Apt 4B', // Optional apartment/suite
918
- city: 'New York',
919
- state: 'NY',
920
- zip: '10001',
921
- country: 'United States' // Optional, will be included in formatted address
922
- },
923
- {
924
- lat: 40.7505045,
925
- long: -73.9934387
926
- }
927
- );
928
-
929
- // Listen for success/failure via events
930
- window.addEventListener('lce:actions.address_updated', function(event) {
931
- const address = event.detail.data;
932
- console.log('✅ Address set!', address.formattedAddress);
933
- updateShippingOptions(address.coordinates);
934
- });
935
-
936
- window.addEventListener('lce:actions.address_failed', function(event) {
937
- const error = event.detail.data;
938
- console.log('❌ Address failed:', error.message);
939
- showAddressForm();
940
- });
941
-
942
- // Get current address
943
- const address = actions.address.getDetails();
944
-
945
- // Clear saved address
946
- actions.address.clear();
947
- ```
948
-
949
- #### Clear Address - Complete Reset
950
-
951
- The `actions.address.clear()` action performs a comprehensive reset of the user's address and shopping session:
952
-
953
- **What it clears:**
954
- - ✅ **Address Data**: Removes all saved address information (street, city, state, zip, coordinates)
955
- - ✅ **Cart Contents**: Completely resets the cart (removes all items, totals, promo codes)
956
- - ✅ **Local Storage**: Completely removes the localStorage entry and its value
957
- - ✅ **Database**: Deletes the persisted store from the server database
958
- - ✅ **Checkout State**: Resets any pending checkout information
959
-
960
- **Why it resets the cart:**
961
- When an address is cleared, the cart must be reset because:
962
- - Cart items have location-specific pricing and availability
963
- - Fulfillment options are tied to specific addresses
964
- - Delivery fees and shipping costs depend on location
965
- - Without a valid address, cart operations would fail or show incorrect data
966
-
967
- **Events fired:**
968
- - `lce:actions.address_cleared` - Address successfully cleared
969
- - `lce:actions.cart_reset` - Cart successfully reset
970
-
971
- **Use cases:**
972
- - Guest checkout option (clear previous user's data)
973
- - Location change (start fresh with new address)
974
- - Privacy compliance (complete data removal)
975
- - Testing/development (reset to clean state)
976
-
977
- **Notes**:
978
- - To find Google Places IDs for the `setAddressByPlacesId` action, use the [Google Places ID Finder](https://developers.google.com/maps/documentation/places/web-service/place-id#find-id)
979
- - The `setAddressManually` action automatically generates a Google Places API-formatted address string from the provided components
980
- - Manual addresses have an empty Places ID (as they don't come from Google Places API)
981
-
982
- **Action Feedback**: All actions provide feedback through events. Listen for success/failure events to handle results and provide user feedback.
983
-
984
- ### Cart Actions
985
-
986
- ```js
987
- // Control cart visibility
988
- actions.cart.openCart();
989
- actions.cart.closeCart();
990
- actions.cart.toggleCart();
991
-
992
- // Add products to cart
993
- await actions.cart.addProduct([{
994
- identifier: 'product-123',
995
- fulfillmentType: 'shipping', // or 'onDemand'
996
- quantity: 2
997
- }]);
998
-
999
- // Listen for add product feedback
1000
- window.addEventListener('lce:actions.cart_product_add_success', function(event) {
1001
- const { itemsAdded, identifiers } = event.detail.data;
1002
- console.log(`✅ Added ${itemsAdded} products to cart:`, identifiers);
1003
- showSuccessMessage('Products added to cart!');
1004
- });
1005
-
1006
- window.addEventListener('lce:actions.cart_product_add_failed', function(event) {
1007
- const { identifiers, error } = event.detail.data;
1008
- console.log(`❌ Failed to add products:`, error);
1009
- showErrorMessage('Could not add products. Please try again.');
1010
- });
1011
-
1012
- // Apply promo codes
1013
- await actions.cart.applyPromoCode('WELCOME10');
1014
-
1015
- // Listen for promo code feedback
1016
- window.addEventListener('lce:actions.cart_promo_code_applied', function(event) {
1017
- const { discount, newTotal } = event.detail.data;
1018
- console.log(`✅ Promo applied! Discount: $${discount}, New total: $${newTotal}`);
1019
- showSavingsMessage(discount);
1020
- });
1021
-
1022
- window.addEventListener('lce:actions.cart_promo_code_failed', function(event) {
1023
- const { error } = event.detail.data;
1024
- console.log(`❌ Promo failed:`, error);
1025
- showErrorMessage('Promo code could not be applied');
1026
- });
1027
-
1028
- // Remove promo codes
1029
- await actions.cart.removePromoCode();
1030
-
1031
- // Get cart details
1032
- const cart = actions.cart.getDetails();
1033
- console.log(cart.itemCount, cart.amounts.total, cart.amounts.giftCardTotal);
1034
-
1035
- // Reset cart
1036
- await actions.cart.resetCart();
1037
- ```
1038
-
1039
- ### Checkout Actions
1040
-
1041
- ```js
1042
- // Control checkout visibility
1043
- actions.checkout.openCheckout();
1044
- actions.checkout.closeCheckout();
1045
- actions.checkout.toggleCheckout();
1046
-
1047
- // Pre-fill customer information
1048
- actions.checkout.updateCustomerInfo({
1049
- firstName: 'John',
1050
- lastName: 'Doe',
1051
- email: 'john@example.com',
1052
- phone: '+1234567890'
1053
- });
1054
-
1055
- // Pre-fill billing information
1056
- actions.checkout.updateBillingInfo({
1057
- firstName: 'John',
1058
- lastName: 'Doe',
1059
- street1: '123 Main St',
1060
- city: 'Anytown',
1061
- state: 'CA',
1062
- zipCode: '12345'
1063
- });
1064
-
1065
- // Manage gift options
1066
- await actions.checkout.toggleIsGift(true);
1067
- actions.checkout.updateGiftInfo({
1068
- giftMessage: 'Happy Birthday!',
1069
- giftFrom: 'Your Friend'
1070
- });
1071
-
1072
- // Apply discounts and gift cards
1073
- await actions.checkout.applyPromoCode('SAVE20');
1074
- await actions.checkout.applyGiftCard('GIFT123');
1075
-
1076
- // Listen for checkout promo code feedback
1077
- window.addEventListener('lce:actions.checkout_promo_code_applied', function(event) {
1078
- const { discount, newTotal } = event.detail.data;
1079
- console.log(`✅ Checkout promo applied! Saved: $${discount}`);
1080
- updateCheckoutTotal(newTotal);
1081
- });
1082
-
1083
- window.addEventListener('lce:actions.checkout_promo_code_failed', function(event) {
1084
- const { error } = event.detail.data;
1085
- console.log(`❌ Checkout promo failed:`, error);
1086
- showCheckoutError('Promo code could not be applied');
1087
- });
1088
-
1089
- // Listen for gift card feedback
1090
- window.addEventListener('lce:actions.checkout_gift_card_applied', function(event) {
1091
- const { newTotal } = event.detail.data;
1092
- console.log('✅ Gift card applied successfully!');
1093
- updateCheckoutTotal(newTotal);
1094
- showSuccessMessage('Gift card applied to your order');
1095
- });
1096
-
1097
- window.addEventListener('lce:actions.checkout_gift_card_failed', function(event) {
1098
- const { error } = event.detail.data;
1099
- console.log(`❌ Gift card failed:`, error);
1100
- showCheckoutError('Gift card could not be applied');
1101
- });
1102
-
1103
- // Get checkout details (safe, non-sensitive data only)
1104
- const checkout = actions.checkout.getDetails();
1105
- console.log(checkout.itemCount, checkout.amounts.total, checkout.isGift);
1106
- console.log(checkout.hasAgeVerify, checkout.hasPromoCode, checkout.hasGiftCards);
1107
- console.log(checkout.acceptedAccountCreation, checkout.billingSameAsShipping);
1108
- console.log(checkout.marketingPreferences);
1109
-
1110
- // Configure checkout options
1111
- await actions.checkout.toggleBillingSameAsShipping(true);
1112
- actions.checkout.toggleMarketingPreferences('canEmail', true);
1113
- ```
1114
-
1115
- See [`docs/ACTIONS.md`](docs/ACTIONS.md) for complete action reference with business use cases.
1116
-
1117
- ## 📡 Events
1118
-
1119
- The SDK emits real-time events for all user interactions. Listen to these events to trigger custom behavior:
1120
-
1121
- ```js
1122
- // Listen for specific events
1123
- window.addEventListener('lce:actions.product_add_to_cart', function(event) {
1124
- const data = event.detail.data;
1125
- console.log('Added to cart:', data.identifier);
1126
-
1127
- // Your custom logic here
1128
- analytics.track('Product Added', {
1129
- identifier: data.identifier,
1130
- quantity: data.quantity,
1131
- upc: data.upc
1132
- });
1133
- });
1134
-
1135
- // Or use the helper methods (available after initialization)
1136
- window.elements.onAllForms((data, metadata) => {
1137
- console.log('Form Event', { data, metadata });
1138
- });
1139
-
1140
- window.elements.onAllActions((data, metadata) => {
1141
- console.log('Action Event', { data, metadata });
1142
- });
1143
- ```
1144
-
1145
- ### Available Events
1146
-
1147
- #### Product Events
1148
- - `lce:actions.product_loaded` - Product component loaded with comprehensive product details (region, country, abv, proof, age, variety, vintage, descriptions, tasting notes)
1149
- - `lce:actions.product_add_to_cart` - Item added to cart
1150
- - `lce:actions.product_quantity_increase` - Quantity increased
1151
- - `lce:actions.product_quantity_decrease` - Quantity decreased
1152
- - `lce:actions.product_size_changed` - Product size/variant changed
1153
- - `lce:actions.product_fulfillment_type_changed` - Delivery method changed
1154
-
1155
- #### Cart Events
1156
- - `lce:actions.cart_loaded` - Cart data loaded with complete cart information (itemCount, all amounts including giftCardTotal, detailed item data)
1157
- - `lce:actions.cart_opened` - Cart displayed
1158
- - `lce:actions.cart_closed` - Cart hidden
1159
- - `lce:actions.cart_updated` - Cart contents changed
1160
- - `lce:actions.cart_item_added` - Item added
1161
- - `lce:actions.cart_item_removed` - Item removed
1162
- - `lce:actions.cart_reset` - Cart cleared
1163
-
1164
- #### Checkout Events
1165
- - `lce:actions.checkout_loaded` - Checkout data loaded with comprehensive details (acceptedAccountCreation, hasSubstitutionPolicy, billingSameAsShipping, marketing preferences, detailed items)
1166
- - `lce:actions.checkout_opened` - Checkout started
1167
- - `lce:actions.checkout_closed` - Checkout abandoned
1168
- - `lce:actions.checkout_submit_started` - Order submission began
1169
- - `lce:actions.checkout_submit_completed` - Order completed successfully
1170
- - `lce:actions.checkout_submit_failed` - Order failed
1171
- - `lce:actions.checkout_customer_information_updated` - Customer info entered (returns boolean only, no sensitive data)
1172
- - `lce:actions.checkout_gift_information_updated` - Gift recipient info entered (returns boolean only, no sensitive data)
1173
- - `lce:actions.checkout_billing_information_updated` - Billing info entered (returns boolean only, no sensitive data)
1174
-
1175
- **Security Note:** Form update events return only `boolean: true` to track completion without exposing sensitive customer information (names, emails, phone numbers, addresses, etc.). This protects your customers from malicious scripts and data breaches.
1176
-
1177
- #### Address Events
1178
- - `lce:actions.address_updated` - Address information changed
1179
- - `lce:actions.address_cleared` - Address removed
1180
-
1181
- See [`docs/EVENTS.md`](docs/EVENTS.md) for complete event reference with all available fields and implementation examples.
1182
-
1183
- ## 🎨 Themes & Customization
1184
-
1185
- The SDK provides a theming system that lets you match components to your brand.
1186
-
1187
- ### Global Theming
1188
-
1189
- ```js
1190
- const client = await Elements('YOUR_API_KEY', {
1191
- customTheme: {
1192
- global: {
1193
- theme: {
1194
- primaryColor: '#007bff',
1195
- accentColor: '#6c757d',
1196
- successColor: '#28a745',
1197
- errorColor: '#dc3545',
1198
- warningColor: '#ffc107',
1199
- defaultTextColor: '#212529',
1200
- selectedTextColor: '#ffffff',
1201
- linkTextColor: '#1d4ed8',
1202
- drawerBackgroundColor: '#ffffff',
1203
- buttonCornerRadius: '8px',
1204
- cardCornerRadius: '12px',
1205
- headingFont: {
1206
- name: 'Inter',
1207
- weights: [600, 700]
1208
- },
1209
- paragraphFont: {
1210
- name: 'Inter',
1211
- weights: [400, 500]
1212
- }
1213
- },
1214
- layout: {
1215
- enablePersonalization: true,
1216
- personalizationText: 'Customize your product',
1217
- personalizationCardStyle: 'outlined',
1218
- allowPromoCodes: true,
1219
- inputFieldStyle: 'outlined',
1220
- poweredByMode: 'light'
1221
- }
1222
- }
1223
- }
1224
- });
1225
- ```
1226
-
1227
- ### Component-Specific Theming
1228
-
1229
- #### Product Component
1230
-
1231
- ```js
1232
- customTheme: {
1233
- product: {
1234
- theme: {
1235
- backgroundColor: '#ffffff'
1236
- },
1237
- layout: {
1238
- showImages: true,
1239
- showTitle: true,
1240
- showDescription: true,
1241
- showQuantityCounter: true,
1242
- quantityCounterStyle: 'outlined',
1243
- fulfillmentDisplay: 'carousel',
1244
- enableShippingFulfillment: true,
1245
- enableOnDemandFulfillment: true,
1246
- addToCartButtonText: 'Add to Cart',
1247
- buyNowButtonText: 'Buy Now'
1248
- }
1249
- }
1250
- }
1251
- ```
1252
-
1253
- #### Cart Component
1254
-
1255
- ```js
1256
- customTheme: {
1257
- cart: {
1258
- theme: {
1259
- backgroundColor: '#ffffff'
1260
- },
1261
- layout: {
1262
- showQuantityCounter: true,
1263
- quantityCounterStyle: 'outlined',
1264
- drawerHeaderText: 'Your Cart',
1265
- goToCheckoutButtonText: 'Checkout'
1266
- }
1267
- }
1268
- }
1269
- ```
1270
-
1271
- #### Checkout Component
1272
-
1273
- ```js
1274
- customTheme: {
1275
- checkout: {
1276
- theme: {
1277
- backgroundColor: '#ffffff',
1278
- checkoutCompleted: {
1279
- customLogo: 'https://yourdomain.com/logo.png',
1280
- customText: 'Thank you for your order!'
1281
- }
1282
- },
1283
- layout: {
1284
- emailOptIn: {
1285
- show: true,
1286
- checked: false,
1287
- text: 'Email me with news'
1288
- },
1289
- smsOptIn: {
1290
- show: true,
1291
- checked: false,
1292
- text: 'Text me updates'
1293
- },
1294
- allowGiftCards: true,
1295
- drawerHeaderText: 'Checkout',
1296
- placeOrderButtonText: 'Place Order'
1297
- }
1298
- }
1299
- }
1300
- ```
1301
-
1302
- #### Address Component
1303
-
1304
- ```js
1305
- customTheme: {
1306
- address: {
1307
- theme: {
1308
- backgroundColor: '#ffffff'
1309
- }
1310
- }
1311
- }
1312
- ```
1313
-
1314
- ### Dynamic Theme Updates (Builder Mode)
1315
-
1316
- In development with `isBuilder: true`, update themes in real-time:
1317
-
1318
- ```js
1319
- const client = await Elements('YOUR_API_KEY', {
1320
- env: 'development',
1321
- isBuilder: true
1322
- });
1323
-
1324
- // Update global theme
1325
- await client.builder.updateComponentGlobalConfigs({
1326
- theme: { primaryColor: '#ff6b6b' }
1327
- });
1328
-
1329
- // Update component-specific themes
1330
- await client.builder.updateProductComponent({
1331
- layout: { addToCartButtonText: 'Add to Bag' }
1332
- });
1333
-
1334
- client.builder.updateCartComponent({
1335
- layout: { drawerHeaderText: 'Shopping Bag' }
1336
- });
1337
-
1338
- client.builder.updateCheckoutComponent({
1339
- layout: { placeOrderButtonText: 'Complete Purchase' }
1340
- });
1341
-
1342
- client.builder.updateAddressComponent({
1343
- theme: { backgroundColor: '#f8f9fa' }
1344
- });
1345
- ```
1346
-
1347
- **📖 For complete theming documentation:** See [`docs/THEMING.md`](docs/THEMING.md)
1348
-
1349
- ---
1350
-
1351
- ## 🎁 Features Deep Dive
1352
-
1353
- ### Product Personalization (Engraving)
1354
-
1355
- The SDK provides a comprehensive personalization/engraving feature for products that support it. The personalization experience varies based on context:
1356
-
1357
- #### Product View
1358
- When browsing products, customers can add personalization through an enhanced form that includes:
1359
- - Product information with pricing
1360
- - Fulfillment/retailer selection (with pricing comparison)
1361
- - Multi-line engraving inputs with character limits
1362
- - Real-time price updates as customers select different retailers
1363
- - Add-to-cart with personalization in one step
1364
-
1365
- ```js
1366
- // Personalization appears automatically for engravable products
1367
- // Customers can add engraving text and select which retailer to fulfill from
1368
-
1369
- // Listen for when personalization is added via add-to-cart
1370
- window.addEventListener('lce:actions.product_add_to_cart', (event) => {
1371
- const { hasEngraving, engravingLines } = event.detail.data;
1372
- if (hasEngraving) {
1373
- console.log('Customer personalized:', engravingLines);
1374
- }
1375
- });
1376
- ```
1377
-
1378
- #### Cart View
1379
- In the cart, personalized items display:
1380
- - Personalization text lines
1381
- - Engraving fee (per item and total for quantity)
1382
- - **Edit** button to modify the personalization
1383
- - **Remove** button to remove personalization
1384
-
1385
- ```js
1386
- // Customers can edit or remove engraving from cart items
1387
- window.addEventListener('lce:actions.cart_item_engraving_updated', (event) => {
1388
- const { identifier, engravingLines } = event.detail.data;
1389
- console.log('Cart item engraving updated:', engravingLines);
1390
- });
1391
- ```
1392
-
1393
- #### Checkout View
1394
- During checkout, personalized items show:
1395
- - Personalization text lines (read-only)
1396
- - Engraving fee included in pricing
1397
- - **Remove** button only (editing not allowed in checkout)
1398
-
1399
- **Design Decision:** Editing personalization during checkout is intentionally disabled to prevent order processing complications. Customers must return to the cart to make changes.
1400
-
1401
- #### Theming & Configuration
1402
-
1403
- Control personalization display through global configuration:
1404
-
1405
- ```js
1406
- customTheme: {
1407
- global: {
1408
- layout: {
1409
- enablePersonalization: true,
1410
- personalizationText: 'Personalize your product',
1411
- personalizationCardStyle: 'outlined' // or 'filled'
1412
- }
1413
- }
1414
- }
1415
- ```
1416
-
1417
- #### Key Features
1418
- - **Smart pricing:** Automatically includes engraving fees in product price
1419
- - **Retailer selection:** Compare prices from different retailers during personalization
1420
- - **Character limits:** Enforces maximum characters per line
1421
- - **Uppercase conversion:** Engraving text is automatically converted to uppercase
1422
- - **Multi-line support:** Products can support 1 or more engraving lines
1423
- - **Fee transparency:** Shows per-item and total fees (e.g., "$5.00 ($2.50 ea)")
1424
-
1425
- **Note:** Personalization is automatically enabled for products that support it. The SDK handles all UI, validation, and state management.
1426
-
1427
- ### Gift Options
1428
-
1429
- Allow orders to be marked as gifts with custom messages:
1430
-
1431
- ```js
1432
- // Enable via theme
1433
- customTheme: {
1434
- checkout: {
1435
- layout: {
1436
- allowGiftOptions: true
1437
- }
1438
- }
1439
- }
1440
-
1441
- // Toggle gift mode programmatically
1442
- await client.actions.checkout.toggleIsGift(true);
1443
-
1444
- // Set gift message
1445
- await client.actions.checkout.updateGiftInfo({
1446
- recipientName: 'John Doe',
1447
- message: 'Happy Birthday!'
1448
- });
1449
-
1450
- // Listen for gift toggles
1451
- window.addEventListener('lce:actions.checkout_is_gift_toggled', (event) => {
1452
- const { isGift } = event.detail.data;
1453
- console.log('Order is gift:', isGift);
1454
- });
1455
- ```
1456
-
1457
- ### Tips (On-Demand Delivery)
1458
-
1459
- Allow customers to tip delivery drivers:
1460
-
1461
- ```js
1462
- // Tips are automatically enabled for onDemand fulfillment types
1463
-
1464
- // Listen for tip updates
1465
- window.addEventListener('lce:actions.checkout_tip_updated', (event) => {
1466
- const { tipAmount, total } = event.detail.data;
1467
- console.log(`Customer tipped $${tipAmount}`);
1468
- });
1469
- ```
1470
-
1471
- Tips are calculated as a percentage or fixed amount and added to the order total.
1472
-
1473
- ### Gift Cards
1474
-
1475
- Accept gift card payments at checkout:
1476
-
1477
- ```js
1478
- // Enable via theme
1479
- customTheme: {
1480
- checkout: {
1481
- layout: {
1482
- allowGiftCards: true
1483
- }
1484
- }
1485
- }
1486
-
1487
- // Apply gift card programmatically
1488
- await client.actions.checkout.applyGiftCard('GIFT-1234-5678-9012');
1489
-
1490
- // Remove gift card
1491
- await client.actions.checkout.removeGiftCard('GIFT-1234-5678-9012');
1492
-
1493
- // Listen for gift card events
1494
- window.addEventListener('lce:actions.checkout_gift_card_applied', (event) => {
1495
- const { newTotal } = event.detail.data;
1496
- console.log(`Gift card applied! New total: $${newTotal}`);
1497
- });
1498
-
1499
- window.addEventListener('lce:actions.checkout_gift_card_failed', (event) => {
1500
- const { error } = event.detail.data;
1501
- console.log('Gift card failed:', error);
1502
- });
1503
- ```
1504
-
1505
- ### Promo Codes
1506
-
1507
- Apply promotional discount codes:
1508
-
1509
- ```js
1510
- // Apply to cart
1511
- await client.actions.cart.applyPromoCode('SUMMER20');
1512
-
1513
- // Apply to checkout
1514
- await client.actions.checkout.applyPromoCode('SAVE10');
1515
-
1516
- // Remove promo code
1517
- await client.actions.cart.removePromoCode();
1518
-
1519
- // Listen for promo events
1520
- window.addEventListener('lce:actions.cart_promo_code_applied', (event) => {
1521
- const { discount, newTotal } = event.detail.data;
1522
- console.log(`Promo applied! Saved $${discount}! New total: $${newTotal}`);
1523
- });
1524
-
1525
- window.addEventListener('lce:actions.cart_promo_code_failed', (event) => {
1526
- const { error } = event.detail.data;
1527
- console.log('Promo failed:', error);
1528
- });
1529
- ```
1530
-
1531
- ### Promo Ticker
1532
-
1533
- Display rotating promotional messages at the top of your site:
1534
-
1535
- ```js
1536
- // Via initialization config
1537
- const client = await Elements('YOUR_API_KEY', {
1538
- promoTicker: [
1539
- {
1540
- promoCode: 'FREESHIP',
1541
- text: ['Free Shipping Today!', 'Use code FREESHIP'],
1542
- separator: '•',
1543
- activeFrom: '2025-01-01T00:00:00Z',
1544
- activeUntil: '2025-12-31T23:59:59Z'
1545
- },
1546
- {
1547
- promoCode: 'SAVE20',
1548
- text: ['20% Off Sitewide', 'Limited Time Only'],
1549
- separator: '|',
1550
- activeFrom: '2025-06-01T00:00:00Z',
1551
- activeUntil: '2025-06-30T23:59:59Z'
1552
- }
1553
- ]
1554
- });
1555
-
1556
- // Via auto-init
1557
- <script
1558
- data-liquid-commerce-elements
1559
- data-token="YOUR_API_KEY"
1560
- data-promo-code="FREESHIP"
1561
- data-promo-text="Free Shipping Today!|Use code FREESHIP"
1562
- data-promo-separator="•"
1563
- data-promo-active-from="2025-01-01T00:00:00Z"
1564
- data-promo-active-until="2025-12-31T23:59:59Z"
1565
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
1566
- ></script>
1567
- ```
1568
-
1569
- The ticker automatically rotates messages and only shows active promotions.
1570
-
1571
- ### Marketing Preferences
1572
-
1573
- Allow customers to opt-in to email and SMS marketing:
1574
-
1575
- ```js
1576
- // Set defaults via theme
1577
- customTheme: {
1578
- checkout: {
1579
- layout: {
1580
- emailOptIn: { checked: false, visible: true },
1581
- smsOptIn: { checked: false, visible: true }
1582
- }
1583
- }
1584
- }
1585
-
1586
- // Update preferences programmatically
1587
- await client.actions.checkout.toggleMarketingPreferences('canEmail', true);
1588
- await client.actions.checkout.toggleMarketingPreferences('canSms', true);
1589
-
1590
- // Listen for preference changes
1591
- window.addEventListener('lce:actions.checkout_marketing_preferences_toggled', (event) => {
1592
- const { field, value } = event.detail.data;
1593
- console.log(`Customer ${value ? 'opted-in' : 'opted-out'} of ${field}`);
1594
- });
1595
- ```
1596
-
1597
- ### Purchase Minimum Alerts
1598
-
1599
- Automatically displays alerts when a retailer has minimum purchase requirements. No configuration needed - the SDK handles this automatically based on retailer rules.
1600
-
1601
- ### Age Verification
1602
-
1603
- 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.
1604
-
1605
- ### Pre-Sale Countdown
1606
-
1607
- 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.
1608
-
1609
- ```js
1610
- // Listen for when product is added to cart
1611
- window.addEventListener('lce:actions.product_add_to_cart', (event) => {
1612
- const { productId } = event.detail.data;
1613
- console.log(`Product ${productId} added to cart`);
1614
- });
1615
- ```
1616
-
1617
- ### Product List
1618
-
1619
- Display a filtered, paginated product catalog with infinite scroll. Perfect for category pages, catalog pages, and search results.
1620
-
1621
- #### Auto-Initialization
1622
-
1623
- Add a product list to any page with data attributes:
1624
-
1625
- ```html
1626
- <div data-liquid-commerce-elements-products-list
1627
- data-card="standard"
1628
- data-rows="3"
1629
- data-columns="4"
1630
- data-filters="personalization,pre-order,delivery-options"
1631
- data-product-url="/product/{upc}">
1632
- </div>
1633
- ```
1634
-
1635
- #### Programmatic Injection
1636
-
1637
- ```js
1638
- await client.injectProductList({
1639
- containerId: 'product-list-container',
1640
- rows: 3,
1641
- columns: 4,
1642
- cardVariant: 'standard',
1643
- fillCard: false,
1644
- filters: ['personalization', 'pre-order', 'delivery-options'],
1645
- productUrl: '/product/{upc}'
1646
- });
1647
- ```
1648
-
1649
- #### Features
1650
-
1651
- **Filtering:**
1652
- - **Personalization filter** - Show only products that support engraving/personalization
1653
- - **Pre-order filter** - Show only pre-order products
1654
- - **Delivery options filter** - Filter by `all`, `shipping`, or `onDemand`
1655
-
1656
- **Smart Filter Logic:**
1657
- - When "Same-Day Delivery" is selected, personalization and pre-order filters are automatically disabled
1658
- - When personalization or pre-order is enabled, same-day delivery is automatically disabled
1659
- - Filters work together intelligently to show only compatible product combinations
1660
-
1661
- **Infinite Scroll:**
1662
- - Automatically loads more products as you scroll
1663
- - Shows loading states during pagination
1664
- - Handles "no more products" gracefully
1665
-
1666
- **Address-Aware:**
1667
- - Automatically reloads when address changes
1668
- - Shows availability based on current location
1669
- - Updates product pricing and fulfillment options dynamically
1670
-
1671
- **Product Cards:**
1672
- - Display product image, name, size, and price
1673
- - Show availability status based on location
1674
- - "Add to Cart" button (disabled if unavailable)
1675
- - Clickable product links (if `productUrl` is provided)
1676
- - Presale product support with special handling
1677
-
1678
- **Analytics Tracking:**
1679
- - Automatically tracks `view_item_list` when products load
1680
- - Tracks `select_item` when user clicks a product link
1681
- - GTM integration for e-commerce events
1682
-
1683
- **Loading States:**
1684
- - Shows skeleton loading cards during initial load
1685
- - Displays loading indicator during infinite scroll
1686
- - Error handling with user-friendly messages
1687
-
1688
- **Product URL Templates:**
1689
- - Use `{upc}` placeholder for UPC-based URLs: `/product/{upc}`
1690
- - Use `{grouping}` placeholder for Salsify grouping IDs: `/product/{grouping}`
1691
- - Links open in new tab with proper security attributes
1692
-
1693
- #### Example: Category Page
1694
-
1695
- ```html
1696
- <div id="category-products"
1697
- data-liquid-commerce-elements-products-list
1698
- data-card="standard"
1699
- data-rows="4"
1700
- data-columns="4"
1701
- data-filters="personalization,delivery-options"
1702
- data-product-url="/products/{upc}">
1703
- </div>
1704
-
1705
- <script
1706
- data-liquid-commerce-elements
1707
- data-token="YOUR_API_KEY"
1708
- data-env="production"
1709
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
1710
- ></script>
1711
- ```
1712
-
1713
- #### Example: Search Results
1714
-
1715
- ```js
1716
- const client = await Elements('YOUR_API_KEY', {
1717
- env: 'production'
1718
- });
1719
-
1720
- await client.injectProductList({
1721
- containerId: 'search-results',
1722
- rows: 6,
1723
- columns: 3,
1724
- cardVariant: 'standard',
1725
- fillCard: true,
1726
- filters: ['delivery-options'],
1727
- productUrl: '/search?q={grouping}'
1728
- });
1729
- ```
1730
-
1731
- **Use cases:**
1732
- - Category pages
1733
- - Catalog pages
1734
- - Search results
1735
- - Filtered product browsing
1736
- - Personalized product recommendations
1737
- - Pre-order product showcases
1738
-
1739
- ---
1740
-
1741
- ## 🔧 Core Capabilities
1742
-
1743
- The SDK includes several built-in services that work behind the scenes to provide a robust, production-ready experience.
1744
-
1745
- ### State Management
1746
-
1747
- The SDK uses a centralized store for all state management. Access state data via actions:
1748
-
1749
- ```js
1750
- // Get current cart state
1751
- const cart = await client.actions.cart.getDetails();
1752
- console.log(cart.itemCount, cart.amounts.total, cart.amounts.giftCardTotal);
1753
-
1754
- // Get current checkout state
1755
- const checkout = await client.actions.checkout.getDetails();
1756
- console.log(checkout.amounts.total, checkout.isGift, checkout.acceptedAccountCreation);
1757
- console.log(checkout.billingSameAsShipping, checkout.marketingPreferences);
1758
-
1759
- // Get current address
1760
- const address = await client.actions.address.getDetails();
1761
- console.log(address.formattedAddress, address.coordinates);
1762
-
1763
- // Get product details
1764
- const product = await client.actions.product.getDetails('00619947000020');
1765
- console.log(product.name, product.region, product.variety, product.vintage);
1766
- console.log(product.description, product.tastingNotes);
1767
- ```
1768
-
1769
- **State is persistent:** Cart and address data persist across page reloads using localStorage.
1770
-
1771
- ### Event System (PubSub)
1772
-
1773
- All SDK interactions emit events through a centralized event system:
1774
-
1775
- ```js
1776
- // Subscribe to specific event
1777
- window.addEventListener('lce:actions.cart_updated', (event) => {
1778
- const { previous, current } = event.detail.data;
1779
- console.log('Cart changed from', previous.amounts.total, 'to', current.amounts.total);
1780
- });
1781
-
1782
- // Subscribe to all action events
1783
- if (window.elements) {
1784
- window.elements.onAllActions((data, metadata) => {
1785
- console.log('Action:', metadata.eventName, data);
1786
- });
1787
- }
1788
-
1789
- // Subscribe to all form events
1790
- if (window.elements) {
1791
- window.elements.onAllForms((data, metadata) => {
1792
- console.log('Form:', metadata.eventName, data);
1793
- });
1794
- }
1795
- ```
1796
-
1797
- **Event format:**
1798
- ```js
1799
- {
1800
- detail: {
1801
- data: { /* event-specific payload */ },
1802
- metadata: {
1803
- eventName: 'lce:actions.cart_updated',
1804
- timestamp: 1699564800000,
1805
- source: 'sdk'
1806
- }
1807
- }
1808
- }
1809
- ```
1810
-
1811
- ### Telemetry & Analytics
1812
-
1813
- The SDK automatically tracks user interactions and performance metrics:
1814
-
1815
- - **User interactions:** Add to cart, checkout started, checkout completed
1816
- - **Performance metrics:** Component load times, API response times
1817
- - **Error tracking:** Failed API calls, validation errors
1818
-
1819
- **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.
1820
-
1821
- **Custom Analytics:**
1822
-
1823
- ```js
1824
- // Listen to events for custom analytics tracking
1825
- window.addEventListener('lce:actions.product_add_to_cart', (event) => {
1826
- const { productId, price, quantity } = event.detail.data;
1827
-
1828
- // Track with your analytics provider
1829
- gtag('event', 'add_to_cart', {
1830
- currency: 'USD',
1831
- value: price * quantity,
1832
- items: [{ item_id: productId, quantity }]
1833
- });
1834
-
1835
- // Or Segment
1836
- analytics.track('Product Added', {
1837
- product_id: productId,
1838
- price,
1839
- quantity
1840
- });
1841
- });
1842
- ```
1843
-
1844
- ### Fingerprinting
1845
-
1846
- The SDK generates a unique device fingerprint for fraud prevention and analytics:
1847
-
1848
- ```js
1849
- // Automatically tracked:
1850
- // - Browser fingerprint
1851
- // - Device characteristics
1852
- // - Session information
1853
-
1854
- // Used for:
1855
- // - Fraud detection
1856
- // - Cart persistence across devices
1857
- // - Personalization
1858
- ```
1859
-
1860
- Fingerprinting is handled automatically and requires no configuration.
1861
-
1862
- ### Authentication
1863
-
1864
- The SDK handles authentication automatically using your API key:
1865
-
1866
- ```js
1867
- const client = await Elements('YOUR_API_KEY', {
1868
- env: 'production'
1869
- });
1870
-
1871
- // All API requests include:
1872
- // - API key authentication
1873
- // - CORS headers
1874
- // - Request signing (when required)
1875
- ```
1876
-
1877
- **Token refresh:** The SDK automatically handles token expiration and refresh.
1878
-
1879
- ### Logger
1880
-
1881
- Built-in logging system with configurable levels:
1882
-
1883
- ```js
1884
- const client = await Elements('YOUR_API_KEY', {
1885
- debugMode: 'console' // 'none' | 'console' | 'panel'
1886
- });
1887
-
1888
- // Debug mode options:
1889
- // - 'none': No logging (production default)
1890
- // - 'console': Logs to browser console
1891
- // - 'panel': Shows visual debug panel + console logs
1892
- ```
1893
-
1894
- **Console debug output:**
1895
- ```
1896
- [LCE SDK] Product loaded: product-123
1897
- [LCE SDK] Cart updated: 3 items, $45.99
1898
- [LCE SDK] Checkout started
1899
- [LCE SDK] API call: POST /cart/add (152ms)
1900
- ```
1901
-
1902
- **Debug panel:**
1903
- - Real-time event stream
1904
- - API call inspector
1905
- - State viewer
1906
- - Performance metrics
1907
-
1908
- ### Command Pattern
1909
-
1910
- The SDK uses a command pattern for all operations:
1911
-
1912
- ```js
1913
- // Commands are:
1914
- // - Queued for execution
1915
- // - Retried on failure
1916
- // - Logged for debugging
1917
- // - Cancelable
1918
-
1919
- // Example: Adding to cart
1920
- // 1. Command created: AddToCartCommand
1921
- // 2. Command queued
1922
- // 3. Command executed
1923
- // 4. Success event emitted
1924
- // 5. UI updated
1925
-
1926
- // This ensures:
1927
- // - Consistent error handling
1928
- // - Automatic retries
1929
- // - Full audit trail
1930
- ```
1931
-
1932
- ### Component Factory
1933
-
1934
- Components are created on-demand using a factory pattern:
1935
-
1936
- ```js
1937
- // When you call:
1938
- const components = await client.injectProductElement([
1939
- { containerId: 'pdp-1', identifier: 'product-123' }
1940
- ]);
1941
- // Returns: IInjectedComponent[] - Array of component wrappers
1942
-
1943
- // The SDK:
1944
- // 1. Creates a ProductComponent instance
1945
- // 2. Registers it with the factory
1946
- // 3. Injects it into the DOM
1947
- // 4. Attaches event listeners
1948
- // 5. Loads product data
1949
- // 6. Renders the component
1950
-
1951
- // Components are:
1952
- // - Lazily loaded
1953
- // - Automatically cleaned up
1954
- // - Reusable across pages
1955
- ```
1956
-
1957
- ### Singleton Manager
1958
-
1959
- Core services are managed as singletons:
12
+ [![Zero Dependencies](https://img.shields.io/badge/Dependencies-Zero-brightgreen)](./package.json)
13
+ [![Browser Support](https://img.shields.io/badge/Browsers-2018+-4285F4?logo=googlechrome&logoColor=white)](./docs/v1/reference/browser-support.md)
1960
14
 
1961
- ```js
1962
- // These services are initialized once and reused:
1963
- // - ApiClient
1964
- // - Store
1965
- // - PubSub
1966
- // - Logger
1967
- // - Telemetry
1968
- // - Fingerprint
1969
- // - Auth
15
+ **Add product displays, shopping carts, and checkout flows to any website**
1970
16
 
1971
- // This ensures:
1972
- // - Consistent state
1973
- // - Efficient memory usage
1974
- // - No duplicate API calls
1975
- ```
17
+ </div>
1976
18
 
1977
19
  ---
1978
20
 
1979
- ## 🏗️ Integration Patterns
1980
-
1981
- ### React Integration
1982
-
1983
- ```jsx
1984
- import { useEffect, useState } from 'react';
1985
- import { Elements } from '@liquidcommerce/elements-sdk';
1986
-
1987
- function ProductPage({ productId }) {
1988
- const [client, setClient] = useState(null);
1989
-
1990
- useEffect(() => {
1991
- async function initSDK() {
1992
- const elementsClient = await Elements(process.env.REACT_APP_LCE_API_KEY, {
1993
- env: 'production'
1994
- });
1995
- setClient(elementsClient);
1996
-
1997
- // Inject product
1998
- await elementsClient.injectProductElement([
1999
- { containerId: 'product-container', identifier: productId }
2000
- ]);
2001
-
2002
- // Create cart button
2003
- elementsClient.ui.cartButton('cart-button', true);
2004
- }
2005
-
2006
- initSDK();
2007
-
2008
- // Cleanup
2009
- return () => {
2010
- // SDK handles cleanup automatically
2011
- };
2012
- }, [productId]);
2013
-
2014
- return (
2015
- <div>
2016
- <div id="cart-button"></div>
2017
- <div id="product-container"></div>
2018
- </div>
2019
- );
2020
- }
2021
- ```
2022
-
2023
- ### Vue Integration
2024
-
2025
- ```vue
2026
- <template>
2027
- <div>
2028
- <div ref="cartButton"></div>
2029
- <div ref="productContainer"></div>
2030
- </div>
2031
- </template>
2032
-
2033
- <script>
2034
- import { Elements } from '@liquidcommerce/elements-sdk';
2035
-
2036
- export default {
2037
- name: 'ProductPage',
2038
- props: ['productId'],
2039
- async mounted() {
2040
- this.client = await Elements(process.env.VUE_APP_LCE_API_KEY, {
2041
- env: 'production'
2042
- });
2043
-
2044
- await this.client.injectProductElement([
2045
- { containerId: this.$refs.productContainer.id, identifier: this.productId }
2046
- ]);
2047
-
2048
- this.client.ui.cartButton(this.$refs.cartButton.id, true);
2049
- }
2050
- }
2051
- </script>
2052
- ```
2053
-
2054
- ### Next.js Integration
2055
-
2056
- ```tsx
2057
- 'use client';
2058
-
2059
- import { useEffect } from 'react';
2060
-
2061
- export default function ProductPage({ productId }: { productId: string }) {
2062
- useEffect(() => {
2063
- // Load SDK script
2064
- const script = document.createElement('script');
2065
- script.src = 'https://assets-elements.liquidcommerce.us/all/elements.js';
2066
- script.async = true;
2067
- script.onload = async () => {
2068
- const client = await (window as any).Elements(process.env.NEXT_PUBLIC_LCE_API_KEY, {
2069
- env: 'production'
2070
- });
2071
-
2072
- const components = await client.injectProductElement([
2073
- { containerId: 'product-container', identifier: productId }
2074
- ]);
2075
-
2076
- client.ui.floatingCartButton(true);
2077
- };
2078
- document.body.appendChild(script);
21
+ ## Overview
2079
22
 
2080
- return () => {
2081
- document.body.removeChild(script);
2082
- };
2083
- }, [productId]);
23
+ Elements SDK is a Web Components-based e-commerce SDK that lets you add product displays, a cart, and checkout to any site with minimal code. It’s framework-agnostic, fully themeable, and works via CDN or NPM.
2084
24
 
2085
- return <div id="product-container"></div>;
2086
- }
2087
- ```
2088
-
2089
- ### WordPress Integration
25
+ ## What You Can Build
2090
26
 
2091
- ```html
2092
- <!-- In your theme's header.php or functions.php -->
2093
- <script
2094
- data-liquid-commerce-elements
2095
- data-token="<?php echo get_option('lce_api_key'); ?>"
2096
- data-env="production"
2097
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
2098
- ></script>
27
+ - Product pages with variants, fulfillment options, and add-to-cart
28
+ - Cart drawer with promo codes and totals
29
+ - Checkout drawer or hosted checkout page
30
+ - Multi-product grids and searchable lists
31
+ - Address capture for delivery availability and pricing
2099
32
 
2100
- <!-- In your product template -->
2101
- <div data-lce-product="<?php echo get_post_meta(get_the_ID(), 'product_upc', true); ?>"></div>
2102
- ```
33
+ ## Installation
2103
34
 
2104
- ### Shopify Integration
35
+ ### CDN (Fastest)
2105
36
 
2106
37
  ```html
2107
- <!-- In theme.liquid -->
2108
38
  <script
39
+ defer
2109
40
  data-liquid-commerce-elements
2110
- data-token="{{ settings.lce_api_key }}"
41
+ data-token="YOUR_API_KEY"
2111
42
  data-env="production"
43
+ data-container-1="product"
44
+ data-product-1="00619947000020"
45
+ type="text/javascript"
2112
46
  src="https://assets-elements.liquidcommerce.us/all/elements.js"
2113
47
  ></script>
2114
48
 
2115
- <!-- In product template -->
2116
- <div data-lce-product="{{ product.barcode }}"></div>
2117
- ```
2118
-
2119
- ### Multi-Page Applications
2120
-
2121
- For SPAs and multi-page apps, initialize once and reuse:
2122
-
2123
- ```js
2124
- // app.js (initialize once)
2125
- let elementsClient = null;
2126
-
2127
- async function getElementsClient() {
2128
- if (!elementsClient) {
2129
- elementsClient = await Elements('YOUR_API_KEY', {
2130
- env: 'production'
2131
- });
2132
- }
2133
- return elementsClient;
2134
- }
2135
-
2136
- // product-page.js
2137
- const client = await getElementsClient();
2138
- await client.injectProductElement([
2139
- { containerId: 'pdp-1', identifier: productId }
2140
- ]);
2141
-
2142
- // cart-page.js
2143
- const client = await getElementsClient();
2144
- const cartComponent = await client.injectCartElement('cart-container');
2145
- ```
2146
-
2147
- ---
2148
-
2149
- ## 🚨 Error Handling
2150
-
2151
- ### Initialization Errors
2152
-
2153
- ```js
2154
- try {
2155
- const client = await Elements('YOUR_API_KEY', {
2156
- env: 'production'
2157
- });
2158
- } catch (error) {
2159
- if (error.message.includes('Invalid API key')) {
2160
- console.error('Authentication failed');
2161
- } else if (error.message.includes('Network')) {
2162
- console.error('Network error - check connectivity');
2163
- } else {
2164
- console.error('SDK initialization failed:', error);
2165
- }
2166
- }
2167
- ```
2168
-
2169
- ### Action Errors
2170
-
2171
- All actions emit failure events with detailed error information:
2172
-
2173
- ```js
2174
- // Product loaded successfully
2175
- window.addEventListener('lce:actions.product_loaded', (event) => {
2176
- const { identifier, productData } = event.detail.data;
2177
- console.log(`Product ${identifier} loaded successfully`);
2178
- });
2179
-
2180
- // Cart action failure
2181
- window.addEventListener('lce:actions.cart_product_add_failed', (event) => {
2182
- const { identifiers, error } = event.detail.data;
2183
- console.error('Failed to add products:', error);
2184
-
2185
- // Show user-friendly message
2186
- showNotification('Could not add to cart. Please try again.', 'error');
2187
- });
2188
-
2189
- // Checkout failure
2190
- window.addEventListener('lce:actions.checkout_submit_failed', (event) => {
2191
- const { error, reason } = event.detail.data;
2192
- console.error('Checkout failed:', reason);
2193
-
2194
- // Handle specific errors
2195
- if (reason.includes('payment')) {
2196
- showNotification('Payment declined. Please check your card details.', 'error');
2197
- } else if (reason.includes('inventory')) {
2198
- showNotification('Some items are no longer available.', 'warning');
2199
- } else {
2200
- showNotification('Checkout failed. Please try again.', 'error');
2201
- }
2202
- });
2203
-
2204
- // Address validation failure
2205
- window.addEventListener('lce:actions.address_failed', (event) => {
2206
- const { error } = event.detail.data;
2207
- console.error('Address validation failed:', error);
2208
- showNotification('Please enter a valid address.', 'error');
2209
- });
2210
-
2211
- // Promo code failure
2212
- window.addEventListener('lce:actions.cart_promo_code_failed', (event) => {
2213
- const { code, error } = event.detail.data;
2214
- console.error(`Promo code ${code} failed:`, error);
2215
-
2216
- if (error.includes('expired')) {
2217
- showNotification('This promo code has expired.', 'warning');
2218
- } else if (error.includes('invalid')) {
2219
- showNotification('Invalid promo code.', 'error');
2220
- } else if (error.includes('minimum')) {
2221
- showNotification('Cart minimum not met for this promo.', 'warning');
2222
- }
2223
- });
2224
- ```
2225
-
2226
- ### Network Error Recovery
2227
-
2228
- ```js
2229
- let retryCount = 0;
2230
- const maxRetries = 3;
2231
-
2232
- async function addProductWithRetry(productParams) {
2233
- try {
2234
- await client.actions.cart.addProduct(productParams);
2235
- } catch (error) {
2236
- if (retryCount < maxRetries && error.message.includes('Network')) {
2237
- retryCount++;
2238
- console.log(`Retrying... Attempt ${retryCount}/${maxRetries}`);
2239
- setTimeout(() => addProductWithRetry(productParams), 1000 * retryCount);
2240
- } else {
2241
- console.error('Failed after retries:', error);
2242
- showNotification('Network error. Please check your connection.', 'error');
2243
- }
2244
- }
2245
- }
2246
- ```
2247
-
2248
- ### Global Error Handler
2249
-
2250
- ```js
2251
- // Listen to all failed events
2252
- window.addEventListener('lce:actions.cart_failed', handleError);
2253
- window.addEventListener('lce:actions.checkout_failed', handleError);
2254
- window.addEventListener('lce:actions.address_failed', handleError);
2255
- window.addEventListener('lce:actions.cart_product_add_failed', handleError);
2256
-
2257
- function handleError(event) {
2258
- const { error, context } = event.detail.data;
2259
-
2260
- // Log to error tracking service
2261
- if (window.Sentry) {
2262
- Sentry.captureException(error, {
2263
- tags: { sdk: 'liquid-commerce' },
2264
- extra: context
2265
- });
2266
- }
2267
-
2268
- // Show user notification
2269
- showNotification('Something went wrong. Please try again.', 'error');
2270
- }
2271
- ```
2272
-
2273
- ---
2274
-
2275
- ## ⚡ Performance & Best Practices
2276
-
2277
- ### Lazy Loading Components
2278
-
2279
- Only inject components when needed:
2280
-
2281
- ```js
2282
- // ❌ Don't inject all components upfront
2283
- await client.injectProductElement([/* 50 products */]);
2284
- await client.injectCartElement('cart');
2285
- await client.injectCheckoutElement('checkout');
2286
-
2287
- // ✅ Inject components as user navigates
2288
- // On product page:
2289
- await client.injectProductElement([{ containerId: 'pdp', identifier: productId }]);
2290
-
2291
- // On cart page (when user clicks cart):
2292
- await client.injectCartElement('cart');
2293
-
2294
- // On checkout (when user proceeds):
2295
- await client.injectCheckoutElement('checkout');
49
+ <div id="product"></div>
2296
50
  ```
2297
51
 
2298
- ### Reuse Client Instance
2299
-
2300
- Initialize once, use everywhere:
2301
-
2302
- ```js
2303
- // ❌ Don't create multiple clients
2304
- // page1.js
2305
- const client1 = await Elements('KEY', { env: 'production' });
2306
- // page2.js
2307
- const client2 = await Elements('KEY', { env: 'production' });
2308
-
2309
- // ✅ Create once, reuse
2310
- // app.js
2311
- window.lceClient = await Elements('KEY', { env: 'production' });
52
+ ### NPM (Programmatic)
2312
53
 
2313
- // page1.js
2314
- const client = window.lceClient;
2315
- await client.injectProductElement([...]);
2316
-
2317
- // page2.js
2318
- const client = window.lceClient;
2319
- await client.injectCartElement('cart');
54
+ ```bash
55
+ npm install @liquidcommerce/elements-sdk
2320
56
  ```
2321
57
 
2322
- ### Batch Product Injections
2323
-
2324
- Group product injections together:
2325
-
2326
- ```js
2327
- // ❌ Don't inject products one by one
2328
- await client.injectProductElement([{ containerId: 'p1', identifier: 'id1' }]);
2329
- await client.injectProductElement([{ containerId: 'p2', identifier: 'id2' }]);
2330
- await client.injectProductElement([{ containerId: 'p3', identifier: 'id3' }]);
58
+ ```javascript
59
+ import { Elements } from '@liquidcommerce/elements-sdk';
2331
60
 
2332
- // Inject all products at once
61
+ const client = await Elements('YOUR_API_KEY', { env: 'production' });
2333
62
  await client.injectProductElement([
2334
- { containerId: 'p1', identifier: 'id1' },
2335
- { containerId: 'p2', identifier: 'id2' },
2336
- { containerId: 'p3', identifier: 'id3' }
63
+ { containerId: 'product', identifier: '00619947000020' }
2337
64
  ]);
2338
65
  ```
2339
66
 
2340
- ### Optimize Event Listeners
2341
-
2342
- Use event delegation instead of multiple listeners:
2343
-
2344
- ```js
2345
- // ❌ Don't listen to every event
2346
- window.addEventListener('lce:actions.product_loaded', handler);
2347
- window.addEventListener('lce:actions.product_add_to_cart', handler);
2348
- window.addEventListener('lce:actions.cart_updated', handler);
2349
- // ... 20 more listeners
2350
-
2351
- // ✅ Use consolidated listeners
2352
- window.elements.onAllActions((data, metadata) => {
2353
- switch (metadata.eventName) {
2354
- case 'lce:actions.product_loaded':
2355
- handleProductLoad(data);
2356
- break;
2357
- case 'lce:actions.product_add_to_cart':
2358
- handleAddToCart(data);
2359
- break;
2360
- case 'lce:actions.cart_updated':
2361
- handleCartUpdate(data);
2362
- break;
2363
- }
2364
- });
2365
- ```
2366
-
2367
- ### Defer Non-Critical Operations
2368
-
2369
- Load SDK after critical page content:
2370
-
2371
- ```html
2372
- <!-- ❌ Don't load SDK in <head> -->
2373
- <head>
2374
- <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
2375
- </head>
2376
-
2377
- <!-- ✅ Load SDK with defer or at end of body -->
2378
- <head>
2379
- <script defer src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
2380
- </head>
2381
-
2382
- <!-- Or -->
2383
- <body>
2384
- <!-- Your page content -->
2385
- <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
2386
- </body>
2387
- ```
2388
-
2389
- ### Use Auto-Init for Simple Cases
2390
-
2391
- Auto-init is optimized for performance:
2392
-
2393
- ```html
2394
- <!-- ✅ Auto-init is the fastest way for simple setups -->
2395
- <div data-lce-product="00619947000020"></div>
2396
- <div data-lce-product="00832889005513"></div>
2397
-
2398
- <script
2399
- data-liquid-commerce-elements
2400
- data-token="YOUR_API_KEY"
2401
- data-env="production"
2402
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
2403
- ></script>
2404
- ```
2405
-
2406
- ### Avoid Unnecessary Re-renders
2407
-
2408
- Don't repeatedly inject the same component:
2409
-
2410
- ```js
2411
- // ❌ Don't re-inject on every state change
2412
- function updateProduct() {
2413
- setProductId(newId);
2414
- await client.injectProductElement([{ containerId: 'pdp', identifier: newId }]);
2415
- }
2416
-
2417
- // ✅ Components update automatically on state changes
2418
- // Just inject once
2419
- useEffect(() => {
2420
- client.injectProductElement([{ containerId: 'pdp', identifier: productId }]);
2421
- }, []); // Empty deps - inject once
2422
-
2423
- // Product will auto-update when you call actions
2424
- await client.actions.cart.addProduct([...]);
2425
- ```
2426
-
2427
- ### Cache Frequently Accessed Data
2428
-
2429
- ```js
2430
- // ❌ Don't repeatedly fetch the same data
2431
- async function showCartTotal() {
2432
- const cart = await client.actions.cart.getDetails();
2433
- return cart.amounts.total;
2434
- }
2435
-
2436
- // ✅ Use UI helpers that auto-update
2437
- client.ui.cartSubtotal('cart-total-display');
2438
- client.ui.cartItemsCount('cart-count-display');
2439
-
2440
- // Or cache and listen to updates
2441
- let cachedCart = await client.actions.cart.getDetails();
2442
- window.addEventListener('lce:actions.cart_updated', (event) => {
2443
- cachedCart = event.detail.data.current;
2444
- });
2445
- ```
2446
-
2447
- ### Use CDN for Production
2448
-
2449
- Always use CDN in production for optimal caching:
67
+ ## Core Concepts (Short)
2450
68
 
2451
- ```js
2452
- // CDN (recommended)
2453
- <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
69
+ - **Web Components + Shadow DOM** for framework-agnostic UI and style isolation
70
+ - **Declarative setup** via HTML data attributes
71
+ - **Programmatic setup** via `Elements()` client for dynamic injection
72
+ - **Events** for analytics and custom UI
73
+ - **Actions API** for cart/checkout control
2454
74
 
2455
- // ❌ Don't self-host unless necessary
2456
- <script src="/static/elements.js"></script>
2457
- ```
75
+ ## Components
2458
76
 
2459
- ### Minimize Theme Complexity
77
+ - **Product**: Images, variants, fulfillment, add-to-cart
78
+ - **Cart**: Drawer with items, totals, promo codes
79
+ - **Checkout**: Drawer or hosted page with full purchase flow
80
+ - **Address**: Delivery location capture
81
+ - **Product List**: Filterable, searchable grids
2460
82
 
2461
- Simpler themes = faster rendering:
83
+ ## Key Methods (High Level)
2462
84
 
2463
- ```js
2464
- // Don't override every style property
2465
- customTheme: {
2466
- global: {
2467
- colors: { /* 20 color overrides */ },
2468
- typography: { /* 15 typography overrides */ },
2469
- shadows: { /* 10 shadow overrides */ },
2470
- // ... 100 more overrides
2471
- }
2472
- }
85
+ - `injectProductElement`, `injectCartElement`, `injectCheckoutElement`, `injectAddressElement`
86
+ - `ui.cartButton`, `ui.floatingCartButton`, `ui.cartSubtotal`, `ui.cartItemsCount`
87
+ - `actions.product`, `actions.cart`, `actions.checkout`, `actions.address`
2473
88
 
2474
- // ✅ Override only what's necessary
2475
- customTheme: {
2476
- global: {
2477
- colors: {
2478
- primary: '#007bff',
2479
- secondary: '#6c757d'
2480
- }
2481
- }
2482
- }
89
+ ```javascript
90
+ // Example: add a product and open cart
91
+ await window.elements.actions.cart.addProduct([
92
+ { identifier: '00619947000020', fulfillmentType: 'shipping', quantity: 1 }
93
+ ], true);
2483
94
  ```
2484
95
 
2485
- ### Monitor Performance
96
+ ## Events (High Level)
2486
97
 
2487
- Track SDK performance in production:
2488
-
2489
- ```js
2490
- // Measure initialization time
2491
- const start = performance.now();
2492
- const client = await Elements('YOUR_API_KEY', { env: 'production' });
2493
- console.log(`SDK initialized in ${performance.now() - start}ms`);
98
+ Listen for SDK events to drive analytics or custom UI:
2494
99
 
2495
- // Track component load times
100
+ ```javascript
2496
101
  window.addEventListener('lce:actions.product_loaded', (event) => {
2497
- const { loadTime } = event.detail.metadata;
2498
- console.log(`Product loaded in ${loadTime}ms`);
2499
-
2500
- // Send to analytics
2501
- analytics.track('SDK Component Load', {
2502
- component: 'product',
2503
- duration: loadTime
2504
- });
102
+ console.log('Loaded:', event.detail.data.identifier);
2505
103
  });
2506
- ```
2507
-
2508
- ### Production Checklist
2509
-
2510
- Before going live:
2511
-
2512
- - ✅ Set `env: 'production'`
2513
- - ✅ Set `debugMode: 'none'` (or omit)
2514
- - ✅ Use CDN script URL
2515
- - ✅ Pin to specific version (optional but recommended)
2516
- - ✅ Configure proxy if using ad blockers
2517
- - ✅ Test error handling
2518
- - ✅ Verify event tracking
2519
- - ✅ Check cart persistence
2520
- - ✅ Test on target browsers
2521
- - ✅ Measure performance metrics
2522
104
 
2523
- **Production-ready init:**
2524
-
2525
- ```js
2526
- const client = await Elements('YOUR_PRODUCTION_API_KEY', {
2527
- env: 'production',
2528
- debugMode: 'none',
2529
- customTheme: { /* minimal overrides */ },
2530
- proxy: { baseUrl: 'https://yourdomain.com/api/proxy' }
105
+ window.addEventListener('lce:actions.checkout_submit_completed', (event) => {
106
+ console.log('Order:', event.detail.data.orderId);
2531
107
  });
2532
108
  ```
2533
109
 
2534
- **📖 For debugging and troubleshooting:** See [`docs/TROUBLESHOOTING.md`](docs/TROUBLESHOOTING.md) for comprehensive problem-solving guide.
2535
-
2536
- ---
2537
-
2538
- ## 🔒 Proxy Configuration
2539
-
2540
- Route API requests through your server to avoid ad blockers:
110
+ ## Theming
2541
111
 
2542
- ```js
112
+ ```javascript
2543
113
  const client = await Elements('YOUR_API_KEY', {
2544
114
  env: 'production',
2545
- proxy: {
2546
- baseUrl: 'https://yourdomain.com/api/liquidcommerce',
2547
- headers: {
2548
- 'X-Custom-Header': 'value'
115
+ customTheme: {
116
+ global: {
117
+ theme: {
118
+ primaryColor: '#007bff',
119
+ buttonCornerRadius: '8px'
120
+ }
2549
121
  }
2550
122
  }
2551
123
  });
2552
124
  ```
2553
125
 
2554
- The SDK automatically handles routing and required headers. See [`docs/PROXY.md`](docs/PROXY.md) for complete proxy setup guide with Next.js examples.
2555
-
2556
- ## 📚 Documentation
126
+ ## Integrations
2557
127
 
2558
- **📖 Complete Documentation:**
128
+ Works with any framework. See:
2559
129
 
2560
- - **[Documentation Index](docs/DOCUMENTATION_INDEX.md)** - Complete guide to all documentation
2561
- - **[Configuration Reference](docs/CONFIGURATION.md)** - All configuration options with TypeScript types
2562
- - **[Theming Guide](docs/THEMING.md)** - Complete customization reference
2563
- - **[Actions Reference](docs/ACTIONS.md)** - Programmatic control with business use cases
2564
- - **[Events Reference](docs/EVENTS.md)** - Event system and tracking guide
2565
- - **[Troubleshooting Guide](docs/TROUBLESHOOTING.md)** - Common issues and solutions
2566
- - **[Browser Support](docs/BROWSER_SUPPORT.md)** - Detailed browser compatibility
2567
- - **[Proxy Setup](docs/PROXY.md)** - Ad blocker avoidance configuration
130
+ - [React](./docs/v1/integration/react.md)
131
+ - [Next.js](./docs/v1/integration/nextjs.md)
132
+ - [Vue](./docs/v1/integration/vue.md)
133
+ - [Angular](./docs/v1/integration/angular.md)
134
+ - [Laravel](./docs/v1/integration/laravel.md)
135
+ - [Vanilla JS](./docs/v1/integration/vanilla-js.md)
136
+ - [Proxy Setup](./docs/v1/integration/proxy-setup.md)
2568
137
 
2569
- ---
2570
-
2571
- ## 🏷️ Versioning
2572
-
2573
- This project uses Semantic Versioning. Two CDN environments are available:
2574
-
2575
- - **Production:** `https://assets-elements.liquidcommerce.us/all/elements.js` (stable)
2576
- - **Beta:** `https://assets-elements.liquidcommerce.us/all/beta/elements.js` (pre-release)
138
+ ## Documentation (v1)
2577
139
 
2578
- ## 💬 Support
140
+ - [Start Here](./docs/v1/README.md)
141
+ - [Getting Started](./docs/v1/getting-started/installation.md)
142
+ - [Guides](./docs/v1/guides/)
143
+ - [API Reference](./docs/v1/api/)
144
+ - [Examples](./docs/v1/examples/)
145
+ - [Reference](./docs/v1/reference/)
2579
146
 
2580
- If you need help with your API key, environment selection, or implementation, contact your LiquidCommerce representative.
2581
-
2582
- ---
2583
-
2584
- <div align="center">
147
+ ## Browser Support
2585
148
 
2586
- **Built with ❤️ by the LiquidCommerce Team**
149
+ Chrome 66+, Firefox 60+, Safari 12+, Edge 79+.
150
+ See [Browser Support](./docs/v1/reference/browser-support.md) for details.
2587
151
 
2588
- [Actions Reference](docs/ACTIONS.md) • [Events Guide](docs/EVENTS.md) • [Browser Support](docs/BROWSER_SUPPORT.md) • [Proxy Setup](docs/PROXY.md)
152
+ ## Support
2589
153
 
2590
- </div>
154
+ Contact your LiquidCommerce representative for assistance.