@liquidcommerce/elements-sdk 2.6.0-beta.1 → 2.6.0-beta.100

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 (274) hide show
  1. package/README.md +99 -2517
  2. package/dist/index.checkout.esm.js +17794 -0
  3. package/dist/index.esm.js +26010 -20601
  4. package/dist/ssr-stub.checkout.esm.js +18 -0
  5. package/dist/ssr-stub.esm.js +270 -0
  6. package/dist/types/auto-initialize/checkout.d.ts +2 -0
  7. package/dist/types/auto-initialize/shared-utils.d.ts +50 -0
  8. package/dist/types/{elements-base-client.d.ts → clients/base.d.ts} +15 -2
  9. package/dist/types/clients/builder.d.ts +3 -0
  10. package/dist/types/clients/checkout.d.ts +6 -0
  11. package/dist/types/{elements-client-helper.d.ts → clients/helpers.d.ts} +2 -1
  12. package/dist/types/clients/main.d.ts +3 -0
  13. package/dist/types/constants/core.constant.d.ts +13 -6
  14. package/dist/types/core/a11y/announcer.service.d.ts +16 -0
  15. package/dist/types/core/a11y/focus-manager.service.d.ts +21 -0
  16. package/dist/types/core/a11y/focusable.d.ts +5 -0
  17. package/dist/types/core/a11y/glyph-button.d.ts +8 -0
  18. package/dist/types/core/a11y/index.d.ts +5 -0
  19. package/dist/types/core/a11y/single-select.d.ts +16 -0
  20. package/dist/types/core/api/api-client.service.d.ts +23 -22
  21. package/dist/types/core/api/api-result.d.ts +19 -0
  22. package/dist/types/core/api/auth-client.service.d.ts +39 -26
  23. package/dist/types/core/api/http-client.service.d.ts +0 -8
  24. package/dist/types/core/base-component.service.d.ts +4 -1
  25. package/dist/types/core/client/actions/base-action.service.d.ts +22 -0
  26. package/dist/types/core/client/actions/client-address-action.service.d.ts +18 -0
  27. package/dist/types/core/client/actions/client-cart-action.service.d.ts +38 -0
  28. package/dist/types/core/client/actions/client-checkout-action.service.d.ts +69 -0
  29. package/dist/types/core/client/actions/client-product-action.service.d.ts +15 -0
  30. package/dist/types/core/client/client-action.service.d.ts +6 -67
  31. package/dist/types/core/client/client-config.service.d.ts +9 -5
  32. package/dist/types/core/command/base-command.service.d.ts +2 -2
  33. package/dist/types/core/command/common-command.service.d.ts +2 -1
  34. package/dist/types/core/google-tag-manager.service.d.ts +15 -11
  35. package/dist/types/core/logger/logger.service.d.ts +1 -1
  36. package/dist/types/core/pubsub/interfaces/address.interface.d.ts +6 -12
  37. package/dist/types/core/pubsub/interfaces/cart.interface.d.ts +27 -64
  38. package/dist/types/core/pubsub/interfaces/checkout.interface.d.ts +45 -50
  39. package/dist/types/core/pubsub/interfaces/core.interface.d.ts +11 -6
  40. package/dist/types/core/pubsub/interfaces/product.interface.d.ts +16 -81
  41. package/dist/types/core/pubsub/pubsub.service.d.ts +1 -2
  42. package/dist/types/core/singleton-manager.service.d.ts +12 -8
  43. package/dist/types/core/store/interfaces/address.interface.d.ts +3 -12
  44. package/dist/types/core/store/interfaces/cart.interface.d.ts +16 -55
  45. package/dist/types/core/store/interfaces/checkout.interface.d.ts +18 -108
  46. package/dist/types/core/store/interfaces/core.interface.d.ts +16 -5
  47. package/dist/types/core/store/interfaces/metadata.interface.d.ts +11 -0
  48. package/dist/types/core/store/interfaces/product-list.interface.d.ts +30 -0
  49. package/dist/types/core/store/interfaces/product.interface.d.ts +13 -66
  50. package/dist/types/core/store/store.constant.d.ts +6 -1
  51. package/dist/types/core/store/store.service.d.ts +1 -0
  52. package/dist/types/core/telemetry/telemetry.interface.d.ts +0 -1
  53. package/dist/types/core/telemetry/telemetry.service.d.ts +1 -0
  54. package/dist/types/enums/core.enum.d.ts +40 -1
  55. package/dist/types/enums/index.d.ts +0 -1
  56. package/dist/types/index.checkout.d.ts +8 -0
  57. package/dist/types/index.checkout.umd.d.ts +4 -0
  58. package/dist/types/index.d.ts +8 -3
  59. package/dist/types/interfaces/api/address.interface.d.ts +28 -0
  60. package/dist/types/interfaces/api/cart.interface.d.ts +96 -0
  61. package/dist/types/interfaces/api/checkout.interface.d.ts +239 -0
  62. package/dist/types/interfaces/{cloud → api}/index.d.ts +1 -3
  63. package/dist/types/interfaces/api/product-list.interface.d.ts +39 -0
  64. package/dist/types/interfaces/api/product.interface.d.ts +112 -0
  65. package/dist/types/interfaces/client.interface.d.ts +72 -0
  66. package/dist/types/interfaces/component.interface.d.ts +7 -0
  67. package/dist/types/interfaces/config.interface.d.ts +40 -0
  68. package/dist/types/interfaces/configs/address.interface.d.ts +1 -1
  69. package/dist/types/interfaces/configs/cart.interface.d.ts +1 -1
  70. package/dist/types/interfaces/configs/checkout.interface.d.ts +2 -1
  71. package/dist/types/interfaces/configs/configurations.interface.d.ts +5 -5
  72. package/dist/types/interfaces/configs/global.interface.d.ts +10 -3
  73. package/dist/types/interfaces/configs/index.d.ts +1 -0
  74. package/dist/types/interfaces/configs/product-list.interface.d.ts +49 -0
  75. package/dist/types/interfaces/configs/product.interface.d.ts +4 -1
  76. package/dist/types/interfaces/injection.interface.d.ts +49 -0
  77. package/dist/types/modules/address/address-display.component.d.ts +3 -1
  78. package/dist/types/modules/address/address-input.component.d.ts +10 -1
  79. package/dist/types/modules/address/address.command.d.ts +4 -4
  80. package/dist/types/modules/address/address.interface.d.ts +0 -7
  81. package/dist/types/modules/address/styles/register-styles.d.ts +1 -0
  82. package/dist/types/modules/cart/cart.commands.d.ts +4 -5
  83. package/dist/types/modules/cart/components/cart-body.component.d.ts +3 -1
  84. package/dist/types/modules/cart/components/cart-footer.component.d.ts +0 -1
  85. package/dist/types/modules/cart/components/cart-fulfillment.component.d.ts +0 -2
  86. package/dist/types/modules/cart/components/cart-item-quantity-price.component.d.ts +5 -0
  87. package/dist/types/modules/cart/components/cart-item.component.d.ts +6 -0
  88. package/dist/types/modules/cart/styles/register-styles.d.ts +1 -0
  89. package/dist/types/modules/checkout/checkout.commands.d.ts +27 -10
  90. package/dist/types/modules/checkout/checkout.component.d.ts +2 -0
  91. package/dist/types/modules/checkout/components/checkout-billing.component.d.ts +2 -2
  92. package/dist/types/modules/checkout/components/checkout-completed.component.d.ts +5 -0
  93. package/dist/types/modules/checkout/components/checkout-header.component.d.ts +1 -0
  94. package/dist/types/modules/checkout/components/checkout-item-quantity.component.d.ts +4 -0
  95. package/dist/types/modules/checkout/components/checkout-items.component.d.ts +4 -3
  96. package/dist/types/modules/checkout/components/checkout-payment.component.d.ts +2 -1
  97. package/dist/types/modules/checkout/components/checkout-place-order-button.component.d.ts +2 -0
  98. package/dist/types/modules/checkout/components/checkout-presale-countdown.component.d.ts +14 -1
  99. package/dist/types/modules/checkout/components/checkout-presale-expired.component.d.ts +7 -1
  100. package/dist/types/modules/checkout/components/checkout-stripe-form.component.d.ts +2 -1
  101. package/dist/types/modules/checkout/components/checkout-tips.component.d.ts +2 -2
  102. package/dist/types/modules/checkout/components/promo-pc-gc.component.d.ts +0 -2
  103. package/dist/types/modules/checkout/constant.d.ts +3 -0
  104. package/dist/types/modules/checkout/styles/register-styles.d.ts +1 -0
  105. package/dist/types/modules/product/components/components.d.ts +7 -4
  106. package/dist/types/modules/product/components/product-add-to-cart-section.component.d.ts +7 -1
  107. package/dist/types/modules/product/components/product-description.component.d.ts +1 -0
  108. package/dist/types/modules/product/components/product-drawer.component.d.ts +6 -0
  109. package/dist/types/modules/product/components/product-image-carousel.component.d.ts +5 -0
  110. package/dist/types/modules/product/components/product-options.component.d.ts +2 -1
  111. package/dist/types/modules/product/components/product-retailers-carousel.component.d.ts +4 -0
  112. package/dist/types/modules/product/components/product-retailers-popup-list.component.d.ts +10 -2
  113. package/dist/types/modules/product/product.commands.d.ts +7 -7
  114. package/dist/types/modules/product/styles/register-styles.d.ts +1 -0
  115. package/dist/types/modules/product-list/components/card-components/index.d.ts +5 -0
  116. package/dist/types/modules/product-list/components/card-components/product-badge.d.ts +9 -0
  117. package/dist/types/modules/product-list/components/card-components/product-button.d.ts +11 -0
  118. package/dist/types/modules/product-list/components/card-components/product-price-and-personalization.d.ts +14 -0
  119. package/dist/types/modules/product-list/components/card-components/product-quantity-selector.d.ts +11 -0
  120. package/dist/types/modules/product-list/components/card-components/product-sizes-list.d.ts +14 -0
  121. package/dist/types/modules/product-list/components/filter-components/index.d.ts +7 -0
  122. package/dist/types/modules/product-list/components/filter-components/product-list-apply-filter-button.d.ts +1 -0
  123. package/dist/types/modules/product-list/components/filter-components/product-list-checkbox-filter.d.ts +7 -0
  124. package/dist/types/modules/product-list/components/filter-components/product-list-chip.d.ts +5 -0
  125. package/dist/types/modules/product-list/components/filter-components/product-list-filters-chips.d.ts +13 -0
  126. package/dist/types/modules/product-list/components/filter-components/product-list-fulfillment-filter.d.ts +15 -0
  127. package/dist/types/modules/product-list/components/filter-components/product-list-price-filter.d.ts +22 -0
  128. package/dist/types/modules/product-list/components/filter-components/product-list-toggle-filters.d.ts +7 -0
  129. package/dist/types/modules/product-list/components/index.d.ts +6 -0
  130. package/dist/types/modules/product-list/components/product-list-card-loading.component.d.ts +3 -1
  131. package/dist/types/modules/product-list/components/product-list-card.component.d.ts +36 -30
  132. package/dist/types/modules/product-list/components/product-list-engraving.component.d.ts +12 -0
  133. package/dist/types/modules/product-list/components/product-list-filters.component.d.ts +56 -14
  134. package/dist/types/modules/product-list/components/product-list-product-engraving-lines.component.d.ts +22 -0
  135. package/dist/types/modules/product-list/components/product-list-product-pre-cart.component.d.ts +53 -0
  136. package/dist/types/modules/product-list/components/product-list-search.component.d.ts +25 -0
  137. package/dist/types/modules/product-list/product-list-filter.utils.d.ts +8 -0
  138. package/dist/types/modules/product-list/product-list-query-params.utils.d.ts +3 -0
  139. package/dist/types/modules/product-list/product-list.commands.d.ts +23 -7
  140. package/dist/types/modules/product-list/product-list.component.d.ts +17 -39
  141. package/dist/types/modules/product-list/product-list.constants.d.ts +38 -0
  142. package/dist/types/modules/product-list/product-list.interface.d.ts +65 -0
  143. package/dist/types/modules/product-list/styles/product-list-card.style.d.ts +1 -0
  144. package/dist/types/modules/product-list/styles/product-list-filters.style.d.ts +1 -0
  145. package/dist/types/modules/product-list/styles/register-styles.d.ts +1 -0
  146. package/dist/types/modules/theme-provider/constants/component-groupings.d.ts +1 -0
  147. package/dist/types/modules/theme-provider/constants/css-variable-mappings.d.ts +1 -1
  148. package/dist/types/modules/theme-provider/services/style-registry.service.d.ts +16 -0
  149. package/dist/types/modules/theme-provider/services/stylesheet-generator.service.d.ts +0 -1
  150. package/dist/types/modules/theme-provider/styles/register-styles.d.ts +1 -0
  151. package/dist/types/modules/theme-provider/theme-provider.service.d.ts +2 -2
  152. package/dist/types/modules/ui-components/alert/alert.component.d.ts +1 -1
  153. package/dist/types/modules/ui-components/buttons/buttons-open-cart.component.d.ts +5 -0
  154. package/dist/types/modules/ui-components/drawer/drawer.component.d.ts +15 -0
  155. package/dist/types/modules/ui-components/engraving/engraving-form.component.d.ts +8 -1
  156. package/dist/types/modules/ui-components/engraving/engraving-view.component.d.ts +7 -1
  157. package/dist/types/modules/ui-components/input/index.d.ts +0 -1
  158. package/dist/types/modules/ui-components/input/input.component.d.ts +14 -1
  159. package/dist/types/modules/ui-components/lce-element/lce-element.component.d.ts +2 -1
  160. package/dist/types/modules/ui-components/promo-code-ticker/promo-code-ticker.component.d.ts +1 -1
  161. package/dist/types/modules/ui-components/purchase-min-alert/index.d.ts +0 -1
  162. package/dist/types/modules/ui-components/ui.commands.d.ts +7 -1
  163. package/dist/types/ssr/stub.checkout.d.ts +6 -0
  164. package/dist/types/ssr/stub.d.ts +10 -0
  165. package/dist/types/static/icon/arrow-right.icon.d.ts +1 -1
  166. package/dist/types/static/icon/bag.icon.d.ts +1 -1
  167. package/dist/types/static/icon/check.icon.d.ts +2 -0
  168. package/dist/types/static/icon/checkbox.icon.d.ts +1 -1
  169. package/dist/types/static/icon/chevron-down.icon.d.ts +1 -1
  170. package/dist/types/static/icon/chevron-left.icon.d.ts +1 -1
  171. package/dist/types/static/icon/chevron-up.icon.d.ts +2 -0
  172. package/dist/types/static/icon/close.icon.d.ts +1 -1
  173. package/dist/types/static/icon/error-info.icon.d.ts +1 -1
  174. package/dist/types/static/icon/filter.icon.d.ts +2 -0
  175. package/dist/types/static/icon/icon.a11y.d.ts +1 -0
  176. package/dist/types/static/icon/icon.types.d.ts +1 -0
  177. package/dist/types/static/icon/index.d.ts +3 -0
  178. package/dist/types/static/icon/info.icon.d.ts +1 -1
  179. package/dist/types/static/icon/loading-spinner.icon.d.ts +1 -1
  180. package/dist/types/static/icon/search.icon.d.ts +1 -1
  181. package/dist/types/static/icon/success.icon.d.ts +1 -1
  182. package/dist/types/static/icon/trash.icon.d.ts +1 -1
  183. package/dist/types/static/icon/warning.icon.d.ts +1 -1
  184. package/dist/types/utils/dom-compat.d.ts +2 -0
  185. package/dist/types/utils/format.d.ts +4 -14
  186. package/dist/types/utils/image-bg-removal.d.ts +3 -0
  187. package/dist/types/utils/product-selection.d.ts +16 -0
  188. package/dist/types/utils/product.d.ts +15 -0
  189. package/docs/v1/README.md +213 -0
  190. package/docs/v1/api/actions/address-actions.md +286 -0
  191. package/docs/v1/api/actions/cart-actions.md +364 -0
  192. package/docs/v1/api/actions/checkout-actions.md +527 -0
  193. package/docs/v1/api/actions/product-actions.md +204 -0
  194. package/docs/v1/api/client.md +596 -0
  195. package/docs/v1/api/configuration.md +555 -0
  196. package/docs/v1/api/injection-methods.md +292 -0
  197. package/docs/v1/api/typescript-types.md +423 -0
  198. package/docs/v1/api/ui-helpers.md +200 -0
  199. package/docs/v1/examples/advanced-patterns.md +199 -0
  200. package/docs/v1/examples/checkout-flow.md +90 -0
  201. package/docs/v1/examples/custom-theming.md +63 -0
  202. package/docs/v1/examples/multi-product-page.md +90 -0
  203. package/docs/v1/examples/simple-product-page.md +89 -0
  204. package/docs/v1/getting-started/concepts.md +521 -0
  205. package/docs/v1/getting-started/installation.md +349 -0
  206. package/docs/v1/getting-started/quick-start.md +410 -0
  207. package/docs/v1/guides/accessibility.md +173 -0
  208. package/docs/v1/guides/address-component.md +435 -0
  209. package/docs/v1/guides/best-practices.md +365 -0
  210. package/docs/v1/guides/cart-component.md +757 -0
  211. package/docs/v1/guides/checkout-component.md +670 -0
  212. package/docs/v1/guides/events.md +939 -0
  213. package/docs/v1/guides/product-component.md +735 -0
  214. package/docs/v1/guides/product-list-component.md +630 -0
  215. package/docs/v1/guides/theming.md +228 -0
  216. package/docs/v1/integration/angular.md +39 -0
  217. package/docs/v1/integration/laravel.md +41 -0
  218. package/docs/v1/integration/nextjs.md +69 -0
  219. package/docs/v1/integration/proxy-setup.md +106 -0
  220. package/docs/v1/integration/react.md +64 -0
  221. package/docs/v1/integration/vanilla-js.md +84 -0
  222. package/docs/v1/integration/vue.md +58 -0
  223. package/docs/v1/reference/analytics.md +108 -0
  224. package/docs/v1/reference/browser-support.md +47 -0
  225. package/docs/v1/reference/error-handling.md +83 -0
  226. package/docs/v1/reference/performance.md +52 -0
  227. package/docs/v1/reference/telemetry.md +85 -0
  228. package/docs/v1/reference/troubleshooting.md +135 -0
  229. package/package.json +69 -45
  230. package/dist/types/elements-builder-client.d.ts +0 -2
  231. package/dist/types/elements-client.d.ts +0 -2
  232. package/dist/types/enums/cloud.enum.d.ts +0 -77
  233. package/dist/types/interfaces/cloud/address.interface.d.ts +0 -36
  234. package/dist/types/interfaces/cloud/cart.interface.d.ts +0 -132
  235. package/dist/types/interfaces/cloud/catalog.interface.d.ts +0 -43
  236. package/dist/types/interfaces/cloud/checkout.interface.d.ts +0 -214
  237. package/dist/types/interfaces/cloud/core.interface.d.ts +0 -22
  238. package/dist/types/interfaces/cloud/product.interface.d.ts +0 -158
  239. package/dist/types/interfaces/cloud/retailer.interface.d.ts +0 -67
  240. package/dist/types/interfaces/cloud/user.interface.d.ts +0 -100
  241. package/dist/types/interfaces/core.interface.d.ts +0 -111
  242. package/dist/types/modules/cart/cart.commands.helper.d.ts +0 -9
  243. package/dist/types/modules/checkout/components/checkout.type.d.ts +0 -4
  244. package/dist/types/modules/product/utils/helpers.d.ts +0 -3
  245. package/dist/types/modules/product/utils/retailer-hours.d.ts +0 -9
  246. package/dist/types/modules/theme-provider/styles/address/index.d.ts +0 -1
  247. package/dist/types/modules/theme-provider/styles/cart/index.d.ts +0 -1
  248. package/dist/types/modules/theme-provider/styles/checkout/index.d.ts +0 -1
  249. package/dist/types/modules/theme-provider/styles/product/index.d.ts +0 -3
  250. package/dist/types/modules/theme-provider/styles/product-list/index.d.ts +0 -1
  251. package/dist/types/modules/theme-provider/styles/ui/index.d.ts +0 -3
  252. package/dist/types/modules/ui-components/input/birthdate-input.component.d.ts +0 -53
  253. package/dist/types/modules/ui-components/purchase-min-alert/helpers.d.ts +0 -7
  254. package/dist/types/utils/helper.d.ts +0 -27
  255. package/docs/ACTIONS.md +0 -1300
  256. package/docs/BROWSER_SUPPORT.md +0 -279
  257. package/docs/CONFIGURATION.md +0 -853
  258. package/docs/DOCUMENTATION_INDEX.md +0 -311
  259. package/docs/EVENTS.md +0 -798
  260. package/docs/PROXY.md +0 -228
  261. package/docs/THEMING.md +0 -589
  262. package/docs/TROUBLESHOOTING.md +0 -793
  263. package/umd/elements.js +0 -1
  264. /package/dist/types/{auto-initialize.d.ts → auto-initialize/main.d.ts} +0 -0
  265. /package/dist/types/modules/{theme-provider/styles/address → address/styles}/address.style.d.ts +0 -0
  266. /package/dist/types/modules/{theme-provider/styles/cart → cart/styles}/cart.style.d.ts +0 -0
  267. /package/dist/types/modules/{theme-provider/styles/checkout → checkout/styles}/checkout.style.d.ts +0 -0
  268. /package/dist/types/modules/{theme-provider/styles/product → product/styles}/image-carousel.style.d.ts +0 -0
  269. /package/dist/types/modules/{theme-provider/styles/product → product/styles}/product.style.d.ts +0 -0
  270. /package/dist/types/modules/{theme-provider/styles/product → product/styles}/retailers.style.d.ts +0 -0
  271. /package/dist/types/modules/{theme-provider/styles/product-list → product-list/styles}/product-list.style.d.ts +0 -0
  272. /package/dist/types/modules/{theme-provider/styles/ui → ui-components/styles}/drawer.style.d.ts +0 -0
  273. /package/dist/types/modules/{theme-provider/styles/ui → ui-components/styles}/loading.style.d.ts +0 -0
  274. /package/dist/types/modules/{theme-provider/styles/ui → ui-components/styles}/promo-code-ticker.style.d.ts +0 -0
package/README.md CHANGED
@@ -8,2582 +8,164 @@ Elements SDK
8
8
  <div align="center">
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
- [![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 { discountAmount, newTotal } = event.detail.data;
1018
- console.log(`✅ Promo applied! Discount: $${discountAmount}, New total: $${newTotal}`);
1019
- showSavingsMessage(discountAmount);
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 { discountAmount, newTotal } = event.detail.data;
1079
- console.log(`✅ Checkout promo applied! Saved: $${discountAmount}`);
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
- drawerBackgroundColor: '#ffffff',
1202
- buttonCornerRadius: '8px',
1203
- cardCornerRadius: '12px',
1204
- headingFont: {
1205
- name: 'Inter',
1206
- weights: [600, 700]
1207
- },
1208
- paragraphFont: {
1209
- name: 'Inter',
1210
- weights: [400, 500]
1211
- }
1212
- },
1213
- layout: {
1214
- enablePersonalization: true,
1215
- personalizationText: 'Customize your product',
1216
- personalizationCardStyle: 'outlined',
1217
- allowPromoCodes: true,
1218
- inputFieldStyle: 'outlined',
1219
- poweredByMode: 'light'
1220
- }
1221
- }
1222
- }
1223
- });
1224
- ```
1225
-
1226
- ### Component-Specific Theming
1227
-
1228
- #### Product Component
1229
-
1230
- ```js
1231
- customTheme: {
1232
- product: {
1233
- theme: {
1234
- backgroundColor: '#ffffff'
1235
- },
1236
- layout: {
1237
- showImages: true,
1238
- showTitle: true,
1239
- showDescription: true,
1240
- showQuantityCounter: true,
1241
- quantityCounterStyle: 'outlined',
1242
- fulfillmentDisplay: 'carousel',
1243
- enableShippingFulfillment: true,
1244
- enableOnDemandFulfillment: true,
1245
- addToCartButtonText: 'Add to Cart',
1246
- buyNowButtonText: 'Buy Now'
1247
- }
1248
- }
1249
- }
1250
- ```
1251
-
1252
- #### Cart Component
1253
-
1254
- ```js
1255
- customTheme: {
1256
- cart: {
1257
- theme: {
1258
- backgroundColor: '#ffffff'
1259
- },
1260
- layout: {
1261
- showQuantityCounter: true,
1262
- quantityCounterStyle: 'outlined',
1263
- drawerHeaderText: 'Your Cart',
1264
- goToCheckoutButtonText: 'Checkout'
1265
- }
1266
- }
1267
- }
1268
- ```
1269
-
1270
- #### Checkout Component
1271
-
1272
- ```js
1273
- customTheme: {
1274
- checkout: {
1275
- theme: {
1276
- backgroundColor: '#ffffff',
1277
- checkoutCompleted: {
1278
- customLogo: 'https://yourdomain.com/logo.png',
1279
- customText: 'Thank you for your order!'
1280
- }
1281
- },
1282
- layout: {
1283
- emailOptIn: {
1284
- show: true,
1285
- checked: false,
1286
- text: 'Email me with news'
1287
- },
1288
- smsOptIn: {
1289
- show: true,
1290
- checked: false,
1291
- text: 'Text me updates'
1292
- },
1293
- allowGiftCards: true,
1294
- drawerHeaderText: 'Checkout',
1295
- placeOrderButtonText: 'Place Order'
1296
- }
1297
- }
1298
- }
1299
- ```
1300
-
1301
- #### Address Component
1302
-
1303
- ```js
1304
- customTheme: {
1305
- address: {
1306
- theme: {
1307
- backgroundColor: '#ffffff'
1308
- }
1309
- }
1310
- }
1311
- ```
1312
-
1313
- ### Dynamic Theme Updates (Builder Mode)
1314
-
1315
- In development with `isBuilder: true`, update themes in real-time:
1316
-
1317
- ```js
1318
- const client = await Elements('YOUR_API_KEY', {
1319
- env: 'development',
1320
- isBuilder: true
1321
- });
1322
-
1323
- // Update global theme
1324
- await client.builder.updateComponentGlobalConfigs({
1325
- theme: { primaryColor: '#ff6b6b' }
1326
- });
1327
-
1328
- // Update component-specific themes
1329
- await client.builder.updateProductComponent({
1330
- layout: { addToCartButtonText: 'Add to Bag' }
1331
- });
1332
-
1333
- client.builder.updateCartComponent({
1334
- layout: { drawerHeaderText: 'Shopping Bag' }
1335
- });
1336
-
1337
- client.builder.updateCheckoutComponent({
1338
- layout: { placeOrderButtonText: 'Complete Purchase' }
1339
- });
1340
-
1341
- client.builder.updateAddressComponent({
1342
- theme: { backgroundColor: '#f8f9fa' }
1343
- });
1344
- ```
1345
-
1346
- **📖 For complete theming documentation:** See [`docs/THEMING.md`](docs/THEMING.md)
1347
-
1348
- ---
1349
-
1350
- ## 🎁 Features Deep Dive
1351
-
1352
- ### Product Personalization (Engraving)
1353
-
1354
- The SDK provides a comprehensive personalization/engraving feature for products that support it. The personalization experience varies based on context:
1355
-
1356
- #### Product View
1357
- When browsing products, customers can add personalization through an enhanced form that includes:
1358
- - Product information with pricing
1359
- - Fulfillment/retailer selection (with pricing comparison)
1360
- - Multi-line engraving inputs with character limits
1361
- - Real-time price updates as customers select different retailers
1362
- - Add-to-cart with personalization in one step
1363
-
1364
- ```js
1365
- // Personalization appears automatically for engravable products
1366
- // Customers can add engraving text and select which retailer to fulfill from
1367
-
1368
- // Listen for when personalization is added via add-to-cart
1369
- window.addEventListener('lce:actions.product_add_to_cart', (event) => {
1370
- const { hasEngraving, engravingLines } = event.detail.data;
1371
- if (hasEngraving) {
1372
- console.log('Customer personalized:', engravingLines);
1373
- }
1374
- });
1375
- ```
1376
-
1377
- #### Cart View
1378
- In the cart, personalized items display:
1379
- - Personalization text lines
1380
- - Engraving fee (per item and total for quantity)
1381
- - **Edit** button to modify the personalization
1382
- - **Remove** button to remove personalization
1383
-
1384
- ```js
1385
- // Customers can edit or remove engraving from cart items
1386
- window.addEventListener('lce:actions.cart_item_engraving_updated', (event) => {
1387
- const { identifier, engravingLines } = event.detail.data;
1388
- console.log('Cart item engraving updated:', engravingLines);
1389
- });
1390
- ```
1391
-
1392
- #### Checkout View
1393
- During checkout, personalized items show:
1394
- - Personalization text lines (read-only)
1395
- - Engraving fee included in pricing
1396
- - **Remove** button only (editing not allowed in checkout)
1397
-
1398
- **Design Decision:** Editing personalization during checkout is intentionally disabled to prevent order processing complications. Customers must return to the cart to make changes.
1399
-
1400
- #### Theming & Configuration
1401
-
1402
- Control personalization display through global configuration:
1403
-
1404
- ```js
1405
- customTheme: {
1406
- global: {
1407
- layout: {
1408
- enablePersonalization: true,
1409
- personalizationText: 'Personalize your product',
1410
- personalizationCardStyle: 'outlined' // or 'filled'
1411
- }
1412
- }
1413
- }
1414
- ```
1415
-
1416
- #### Key Features
1417
- - **Smart pricing:** Automatically includes engraving fees in product price
1418
- - **Retailer selection:** Compare prices from different retailers during personalization
1419
- - **Character limits:** Enforces maximum characters per line
1420
- - **Uppercase conversion:** Engraving text is automatically converted to uppercase
1421
- - **Multi-line support:** Products can support 1 or more engraving lines
1422
- - **Fee transparency:** Shows per-item and total fees (e.g., "$5.00 ($2.50 ea)")
1423
-
1424
- **Note:** Personalization is automatically enabled for products that support it. The SDK handles all UI, validation, and state management.
1425
-
1426
- ### Gift Options
1427
-
1428
- Allow orders to be marked as gifts with custom messages:
1429
-
1430
- ```js
1431
- // Enable via theme
1432
- customTheme: {
1433
- checkout: {
1434
- layout: {
1435
- allowGiftOptions: true
1436
- }
1437
- }
1438
- }
1439
-
1440
- // Toggle gift mode programmatically
1441
- await client.actions.checkout.toggleIsGift(true);
1442
-
1443
- // Set gift message
1444
- await client.actions.checkout.updateGiftInfo({
1445
- recipientName: 'John Doe',
1446
- message: 'Happy Birthday!'
1447
- });
1448
-
1449
- // Listen for gift toggles
1450
- window.addEventListener('lce:actions.checkout_is_gift_toggled', (event) => {
1451
- const { isGift } = event.detail.data;
1452
- console.log('Order is gift:', isGift);
1453
- });
1454
- ```
1455
-
1456
- ### Tips (On-Demand Delivery)
1457
-
1458
- Allow customers to tip delivery drivers:
1459
-
1460
- ```js
1461
- // Tips are automatically enabled for onDemand fulfillment types
1462
-
1463
- // Listen for tip updates
1464
- window.addEventListener('lce:actions.checkout_tip_updated', (event) => {
1465
- const { tipAmount, total } = event.detail.data;
1466
- console.log(`Customer tipped $${tipAmount}`);
1467
- });
1468
- ```
1469
-
1470
- Tips are calculated as a percentage or fixed amount and added to the order total.
1471
-
1472
- ### Gift Cards
1473
-
1474
- Accept gift card payments at checkout:
1475
-
1476
- ```js
1477
- // Enable via theme
1478
- customTheme: {
1479
- checkout: {
1480
- layout: {
1481
- allowGiftCards: true
1482
- }
1483
- }
1484
- }
1485
-
1486
- // Apply gift card programmatically
1487
- await client.actions.checkout.applyGiftCard('GIFT-1234-5678-9012');
1488
-
1489
- // Remove gift card
1490
- await client.actions.checkout.removeGiftCard('GIFT-1234-5678-9012');
1491
-
1492
- // Listen for gift card events
1493
- window.addEventListener('lce:actions.checkout_gift_card_applied', (event) => {
1494
- const { newTotal } = event.detail.data;
1495
- console.log(`Gift card applied! New total: $${newTotal}`);
1496
- });
1497
-
1498
- window.addEventListener('lce:actions.checkout_gift_card_failed', (event) => {
1499
- const { error } = event.detail.data;
1500
- console.log('Gift card failed:', error);
1501
- });
1502
- ```
1503
-
1504
- ### Promo Codes
1505
-
1506
- Apply promotional discount codes:
1507
-
1508
- ```js
1509
- // Apply to cart
1510
- await client.actions.cart.applyPromoCode('SUMMER20');
1511
-
1512
- // Apply to checkout
1513
- await client.actions.checkout.applyPromoCode('SAVE10');
1514
-
1515
- // Remove promo code
1516
- await client.actions.cart.removePromoCode();
1517
-
1518
- // Listen for promo events
1519
- window.addEventListener('lce:actions.cart_promo_code_applied', (event) => {
1520
- const { discountAmount, newTotal } = event.detail.data;
1521
- console.log(`Promo applied! Saved $${discountAmount}! New total: $${newTotal}`);
1522
- });
1523
-
1524
- window.addEventListener('lce:actions.cart_promo_code_failed', (event) => {
1525
- const { error } = event.detail.data;
1526
- console.log('Promo failed:', error);
1527
- });
1528
- ```
1529
-
1530
- ### Promo Ticker
1531
-
1532
- Display rotating promotional messages at the top of your site:
1533
-
1534
- ```js
1535
- // Via initialization config
1536
- const client = await Elements('YOUR_API_KEY', {
1537
- promoTicker: [
1538
- {
1539
- promoCode: 'FREESHIP',
1540
- text: ['Free Shipping Today!', 'Use code FREESHIP'],
1541
- separator: '•',
1542
- activeFrom: '2025-01-01T00:00:00Z',
1543
- activeUntil: '2025-12-31T23:59:59Z'
1544
- },
1545
- {
1546
- promoCode: 'SAVE20',
1547
- text: ['20% Off Sitewide', 'Limited Time Only'],
1548
- separator: '|',
1549
- activeFrom: '2025-06-01T00:00:00Z',
1550
- activeUntil: '2025-06-30T23:59:59Z'
1551
- }
1552
- ]
1553
- });
1554
-
1555
- // Via auto-init
1556
- <script
1557
- data-liquid-commerce-elements
1558
- data-token="YOUR_API_KEY"
1559
- data-promo-code="FREESHIP"
1560
- data-promo-text="Free Shipping Today!|Use code FREESHIP"
1561
- data-promo-separator="•"
1562
- data-promo-active-from="2025-01-01T00:00:00Z"
1563
- data-promo-active-until="2025-12-31T23:59:59Z"
1564
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
1565
- ></script>
1566
- ```
1567
-
1568
- The ticker automatically rotates messages and only shows active promotions.
1569
-
1570
- ### Marketing Preferences
1571
-
1572
- Allow customers to opt-in to email and SMS marketing:
1573
-
1574
- ```js
1575
- // Set defaults via theme
1576
- customTheme: {
1577
- checkout: {
1578
- layout: {
1579
- emailOptIn: { checked: false, visible: true },
1580
- smsOptIn: { checked: false, visible: true }
1581
- }
1582
- }
1583
- }
1584
-
1585
- // Update preferences programmatically
1586
- await client.actions.checkout.toggleMarketingPreferences('canEmail', true);
1587
- await client.actions.checkout.toggleMarketingPreferences('canSms', true);
1588
-
1589
- // Listen for preference changes
1590
- window.addEventListener('lce:actions.checkout_marketing_preferences_toggled', (event) => {
1591
- const { field, value } = event.detail.data;
1592
- console.log(`Customer ${value ? 'opted-in' : 'opted-out'} of ${field}`);
1593
- });
1594
- ```
1595
-
1596
- ### Purchase Minimum Alerts
1597
-
1598
- Automatically displays alerts when a retailer has minimum purchase requirements. No configuration needed - the SDK handles this automatically based on retailer rules.
1599
-
1600
- ### Age Verification
1601
-
1602
- 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.
1603
-
1604
- ### Pre-Sale Countdown
1605
-
1606
- 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.
1607
-
1608
- ```js
1609
- // Listen for when product is added to cart
1610
- window.addEventListener('lce:actions.product_add_to_cart', (event) => {
1611
- const { productId } = event.detail.data;
1612
- console.log(`Product ${productId} added to cart`);
1613
- });
1614
- ```
1615
-
1616
- ### Product List
1617
-
1618
- Display a filtered, paginated product catalog with infinite scroll. Perfect for category pages, catalog pages, and search results.
1619
-
1620
- #### Auto-Initialization
1621
-
1622
- Add a product list to any page with data attributes:
1623
-
1624
- ```html
1625
- <div data-liquid-commerce-elements-products-list
1626
- data-card="standard"
1627
- data-rows="3"
1628
- data-columns="4"
1629
- data-filters="personalization,pre-order,delivery-options"
1630
- data-product-url="/product/{upc}">
1631
- </div>
1632
- ```
1633
-
1634
- #### Programmatic Injection
1635
-
1636
- ```js
1637
- await client.injectProductList({
1638
- containerId: 'product-list-container',
1639
- rows: 3,
1640
- columns: 4,
1641
- cardVariant: 'standard',
1642
- fillCard: false,
1643
- filters: ['personalization', 'pre-order', 'delivery-options'],
1644
- productUrl: '/product/{upc}'
1645
- });
1646
- ```
1647
-
1648
- #### Features
1649
-
1650
- **Filtering:**
1651
- - **Personalization filter** - Show only products that support engraving/personalization
1652
- - **Pre-order filter** - Show only pre-order products
1653
- - **Delivery options filter** - Filter by `all`, `shipping`, or `onDemand`
1654
-
1655
- **Smart Filter Logic:**
1656
- - When "Same-Day Delivery" is selected, personalization and pre-order filters are automatically disabled
1657
- - When personalization or pre-order is enabled, same-day delivery is automatically disabled
1658
- - Filters work together intelligently to show only compatible product combinations
1659
-
1660
- **Infinite Scroll:**
1661
- - Automatically loads more products as you scroll
1662
- - Shows loading states during pagination
1663
- - Handles "no more products" gracefully
1664
-
1665
- **Address-Aware:**
1666
- - Automatically reloads when address changes
1667
- - Shows availability based on current location
1668
- - Updates product pricing and fulfillment options dynamically
1669
-
1670
- **Product Cards:**
1671
- - Display product image, name, size, and price
1672
- - Show availability status based on location
1673
- - "Add to Cart" button (disabled if unavailable)
1674
- - Clickable product links (if `productUrl` is provided)
1675
- - Presale product support with special handling
1676
-
1677
- **Analytics Tracking:**
1678
- - Automatically tracks `view_item_list` when products load
1679
- - Tracks `select_item` when user clicks a product link
1680
- - GTM integration for e-commerce events
1681
-
1682
- **Loading States:**
1683
- - Shows skeleton loading cards during initial load
1684
- - Displays loading indicator during infinite scroll
1685
- - Error handling with user-friendly messages
1686
-
1687
- **Product URL Templates:**
1688
- - Use `{upc}` placeholder for UPC-based URLs: `/product/{upc}`
1689
- - Use `{grouping}` placeholder for Salsify grouping IDs: `/product/{grouping}`
1690
- - Links open in new tab with proper security attributes
1691
-
1692
- #### Example: Category Page
1693
-
1694
- ```html
1695
- <div id="category-products"
1696
- data-liquid-commerce-elements-products-list
1697
- data-card="standard"
1698
- data-rows="4"
1699
- data-columns="4"
1700
- data-filters="personalization,delivery-options"
1701
- data-product-url="/products/{upc}">
1702
- </div>
1703
-
1704
- <script
1705
- data-liquid-commerce-elements
1706
- data-token="YOUR_API_KEY"
1707
- data-env="production"
1708
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
1709
- ></script>
1710
- ```
1711
-
1712
- #### Example: Search Results
1713
-
1714
- ```js
1715
- const client = await Elements('YOUR_API_KEY', {
1716
- env: 'production'
1717
- });
1718
-
1719
- await client.injectProductList({
1720
- containerId: 'search-results',
1721
- rows: 6,
1722
- columns: 3,
1723
- cardVariant: 'standard',
1724
- fillCard: true,
1725
- filters: ['delivery-options'],
1726
- productUrl: '/search?q={grouping}'
1727
- });
1728
- ```
1729
-
1730
- **Use cases:**
1731
- - Category pages
1732
- - Catalog pages
1733
- - Search results
1734
- - Filtered product browsing
1735
- - Personalized product recommendations
1736
- - Pre-order product showcases
1737
-
1738
- ---
1739
-
1740
- ## 🔧 Core Capabilities
1741
-
1742
- The SDK includes several built-in services that work behind the scenes to provide a robust, production-ready experience.
1743
-
1744
- ### State Management
1745
-
1746
- The SDK uses a centralized store for all state management. Access state data via actions:
1747
-
1748
- ```js
1749
- // Get current cart state
1750
- const cart = await client.actions.cart.getDetails();
1751
- console.log(cart.itemCount, cart.amounts.total, cart.amounts.giftCardTotal);
1752
-
1753
- // Get current checkout state
1754
- const checkout = await client.actions.checkout.getDetails();
1755
- console.log(checkout.amounts.total, checkout.isGift, checkout.acceptedAccountCreation);
1756
- console.log(checkout.billingSameAsShipping, checkout.marketingPreferences);
1757
-
1758
- // Get current address
1759
- const address = await client.actions.address.getDetails();
1760
- console.log(address.formattedAddress, address.coordinates);
1761
-
1762
- // Get product details
1763
- const product = await client.actions.product.getDetails('00619947000020');
1764
- console.log(product.name, product.region, product.variety, product.vintage);
1765
- console.log(product.description, product.tastingNotes);
1766
- ```
1767
-
1768
- **State is persistent:** Cart and address data persist across page reloads using localStorage.
1769
-
1770
- ### Event System (PubSub)
1771
-
1772
- All SDK interactions emit events through a centralized event system:
1773
-
1774
- ```js
1775
- // Subscribe to specific event
1776
- window.addEventListener('lce:actions.cart_updated', (event) => {
1777
- const { previous, current } = event.detail.data;
1778
- console.log('Cart changed from', previous.amounts.total, 'to', current.amounts.total);
1779
- });
1780
-
1781
- // Subscribe to all action events
1782
- if (window.elements) {
1783
- window.elements.onAllActions((data, metadata) => {
1784
- console.log('Action:', metadata.eventName, data);
1785
- });
1786
- }
1787
-
1788
- // Subscribe to all form events
1789
- if (window.elements) {
1790
- window.elements.onAllForms((data, metadata) => {
1791
- console.log('Form:', metadata.eventName, data);
1792
- });
1793
- }
1794
- ```
1795
-
1796
- **Event format:**
1797
- ```js
1798
- {
1799
- detail: {
1800
- data: { /* event-specific payload */ },
1801
- metadata: {
1802
- eventName: 'lce:actions.cart_updated',
1803
- timestamp: 1699564800000,
1804
- source: 'sdk'
1805
- }
1806
- }
1807
- }
1808
- ```
1809
-
1810
- ### Telemetry & Analytics
1811
-
1812
- The SDK automatically tracks user interactions and performance metrics:
1813
-
1814
- - **User interactions:** Add to cart, checkout started, checkout completed
1815
- - **Performance metrics:** Component load times, API response times
1816
- - **Error tracking:** Failed API calls, validation errors
1817
-
1818
- **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.
1819
-
1820
- **Custom Analytics:**
1821
-
1822
- ```js
1823
- // Listen to events for custom analytics tracking
1824
- window.addEventListener('lce:actions.product_add_to_cart', (event) => {
1825
- const { productId, price, quantity } = event.detail.data;
1826
-
1827
- // Track with your analytics provider
1828
- gtag('event', 'add_to_cart', {
1829
- currency: 'USD',
1830
- value: price * quantity,
1831
- items: [{ item_id: productId, quantity }]
1832
- });
1833
-
1834
- // Or Segment
1835
- analytics.track('Product Added', {
1836
- product_id: productId,
1837
- price,
1838
- quantity
1839
- });
1840
- });
1841
- ```
1842
-
1843
- ### Fingerprinting
1844
-
1845
- The SDK generates a unique device fingerprint for fraud prevention and analytics:
1846
-
1847
- ```js
1848
- // Automatically tracked:
1849
- // - Browser fingerprint
1850
- // - Device characteristics
1851
- // - Session information
1852
-
1853
- // Used for:
1854
- // - Fraud detection
1855
- // - Cart persistence across devices
1856
- // - Personalization
1857
- ```
1858
-
1859
- Fingerprinting is handled automatically and requires no configuration.
1860
-
1861
- ### Authentication
1862
-
1863
- The SDK handles authentication automatically using your API key:
1864
-
1865
- ```js
1866
- const client = await Elements('YOUR_API_KEY', {
1867
- env: 'production'
1868
- });
1869
-
1870
- // All API requests include:
1871
- // - API key authentication
1872
- // - CORS headers
1873
- // - Request signing (when required)
1874
- ```
1875
-
1876
- **Token refresh:** The SDK automatically handles token expiration and refresh.
1877
-
1878
- ### Logger
1879
-
1880
- Built-in logging system with configurable levels:
1881
-
1882
- ```js
1883
- const client = await Elements('YOUR_API_KEY', {
1884
- debugMode: 'console' // 'none' | 'console' | 'panel'
1885
- });
1886
-
1887
- // Debug mode options:
1888
- // - 'none': No logging (production default)
1889
- // - 'console': Logs to browser console
1890
- // - 'panel': Shows visual debug panel + console logs
1891
- ```
1892
-
1893
- **Console debug output:**
1894
- ```
1895
- [LCE SDK] Product loaded: product-123
1896
- [LCE SDK] Cart updated: 3 items, $45.99
1897
- [LCE SDK] Checkout started
1898
- [LCE SDK] API call: POST /cart/add (152ms)
1899
- ```
1900
-
1901
- **Debug panel:**
1902
- - Real-time event stream
1903
- - API call inspector
1904
- - State viewer
1905
- - Performance metrics
1906
-
1907
- ### Command Pattern
1908
-
1909
- The SDK uses a command pattern for all operations:
1910
-
1911
- ```js
1912
- // Commands are:
1913
- // - Queued for execution
1914
- // - Retried on failure
1915
- // - Logged for debugging
1916
- // - Cancelable
1917
-
1918
- // Example: Adding to cart
1919
- // 1. Command created: AddToCartCommand
1920
- // 2. Command queued
1921
- // 3. Command executed
1922
- // 4. Success event emitted
1923
- // 5. UI updated
1924
-
1925
- // This ensures:
1926
- // - Consistent error handling
1927
- // - Automatic retries
1928
- // - Full audit trail
1929
- ```
1930
-
1931
- ### Component Factory
1932
-
1933
- Components are created on-demand using a factory pattern:
1934
-
1935
- ```js
1936
- // When you call:
1937
- const components = await client.injectProductElement([
1938
- { containerId: 'pdp-1', identifier: 'product-123' }
1939
- ]);
1940
- // Returns: IInjectedComponent[] - Array of component wrappers
1941
-
1942
- // The SDK:
1943
- // 1. Creates a ProductComponent instance
1944
- // 2. Registers it with the factory
1945
- // 3. Injects it into the DOM
1946
- // 4. Attaches event listeners
1947
- // 5. Loads product data
1948
- // 6. Renders the component
1949
-
1950
- // Components are:
1951
- // - Lazily loaded
1952
- // - Automatically cleaned up
1953
- // - Reusable across pages
1954
- ```
1955
-
1956
- ### Singleton Manager
1957
-
1958
- Core services are managed as singletons:
11
+ [![TypeScript](https://img.shields.io/badge/TypeScript-6+-3178C6?style=for-the-badge&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
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)
1959
14
 
1960
- ```js
1961
- // These services are initialized once and reused:
1962
- // - ApiClient
1963
- // - Store
1964
- // - PubSub
1965
- // - Logger
1966
- // - Telemetry
1967
- // - Fingerprint
1968
- // - Auth
15
+ **Add product displays, shopping carts, and checkout flows to any website**
1969
16
 
1970
- // This ensures:
1971
- // - Consistent state
1972
- // - Efficient memory usage
1973
- // - No duplicate API calls
1974
- ```
17
+ </div>
1975
18
 
1976
19
  ---
1977
20
 
1978
- ## 🏗️ Integration Patterns
1979
-
1980
- ### React Integration
1981
-
1982
- ```jsx
1983
- import { useEffect, useState } from 'react';
1984
- import { Elements } from '@liquidcommerce/elements-sdk';
1985
-
1986
- function ProductPage({ productId }) {
1987
- const [client, setClient] = useState(null);
1988
-
1989
- useEffect(() => {
1990
- async function initSDK() {
1991
- const elementsClient = await Elements(process.env.REACT_APP_LCE_API_KEY, {
1992
- env: 'production'
1993
- });
1994
- setClient(elementsClient);
1995
-
1996
- // Inject product
1997
- await elementsClient.injectProductElement([
1998
- { containerId: 'product-container', identifier: productId }
1999
- ]);
2000
-
2001
- // Create cart button
2002
- elementsClient.ui.cartButton('cart-button', true);
2003
- }
2004
-
2005
- initSDK();
2006
-
2007
- // Cleanup
2008
- return () => {
2009
- // SDK handles cleanup automatically
2010
- };
2011
- }, [productId]);
2012
-
2013
- return (
2014
- <div>
2015
- <div id="cart-button"></div>
2016
- <div id="product-container"></div>
2017
- </div>
2018
- );
2019
- }
2020
- ```
2021
-
2022
- ### Vue Integration
21
+ ## Overview
2023
22
 
2024
- ```vue
2025
- <template>
2026
- <div>
2027
- <div ref="cartButton"></div>
2028
- <div ref="productContainer"></div>
2029
- </div>
2030
- </template>
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.
2031
24
 
2032
- <script>
2033
- import { Elements } from '@liquidcommerce/elements-sdk';
2034
-
2035
- export default {
2036
- name: 'ProductPage',
2037
- props: ['productId'],
2038
- async mounted() {
2039
- this.client = await Elements(process.env.VUE_APP_LCE_API_KEY, {
2040
- env: 'production'
2041
- });
2042
-
2043
- await this.client.injectProductElement([
2044
- { containerId: this.$refs.productContainer.id, identifier: this.productId }
2045
- ]);
2046
-
2047
- this.client.ui.cartButton(this.$refs.cartButton.id, true);
2048
- }
2049
- }
2050
- </script>
2051
- ```
2052
-
2053
- ### Next.js Integration
2054
-
2055
- ```tsx
2056
- 'use client';
2057
-
2058
- import { useEffect } from 'react';
2059
-
2060
- export default function ProductPage({ productId }: { productId: string }) {
2061
- useEffect(() => {
2062
- // Load SDK script
2063
- const script = document.createElement('script');
2064
- script.src = 'https://assets-elements.liquidcommerce.us/all/elements.js';
2065
- script.async = true;
2066
- script.onload = async () => {
2067
- const client = await (window as any).Elements(process.env.NEXT_PUBLIC_LCE_API_KEY, {
2068
- env: 'production'
2069
- });
2070
-
2071
- const components = await client.injectProductElement([
2072
- { containerId: 'product-container', identifier: productId }
2073
- ]);
2074
-
2075
- client.ui.floatingCartButton(true);
2076
- };
2077
- document.body.appendChild(script);
2078
-
2079
- return () => {
2080
- document.body.removeChild(script);
2081
- };
2082
- }, [productId]);
2083
-
2084
- return <div id="product-container"></div>;
2085
- }
2086
- ```
2087
-
2088
- ### WordPress Integration
25
+ ## What You Can Build
2089
26
 
2090
- ```html
2091
- <!-- In your theme's header.php or functions.php -->
2092
- <script
2093
- data-liquid-commerce-elements
2094
- data-token="<?php echo get_option('lce_api_key'); ?>"
2095
- data-env="production"
2096
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
2097
- ></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
2098
32
 
2099
- <!-- In your product template -->
2100
- <div data-lce-product="<?php echo get_post_meta(get_the_ID(), 'product_upc', true); ?>"></div>
2101
- ```
33
+ ## Installation
2102
34
 
2103
- ### Shopify Integration
35
+ ### CDN (Fastest)
2104
36
 
2105
37
  ```html
2106
- <!-- In theme.liquid -->
2107
38
  <script
39
+ defer
2108
40
  data-liquid-commerce-elements
2109
- data-token="{{ settings.lce_api_key }}"
41
+ data-token="YOUR_API_KEY"
2110
42
  data-env="production"
2111
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
43
+ data-container-1="product"
44
+ data-product-1="00619947000020"
45
+ type="text/javascript"
46
+ src="https://elements.reservebar-worker.workers.dev/all/elements.js"
2112
47
  ></script>
2113
48
 
2114
- <!-- In product template -->
2115
- <div data-lce-product="{{ product.barcode }}"></div>
2116
- ```
2117
-
2118
- ### Multi-Page Applications
2119
-
2120
- For SPAs and multi-page apps, initialize once and reuse:
2121
-
2122
- ```js
2123
- // app.js (initialize once)
2124
- let elementsClient = null;
2125
-
2126
- async function getElementsClient() {
2127
- if (!elementsClient) {
2128
- elementsClient = await Elements('YOUR_API_KEY', {
2129
- env: 'production'
2130
- });
2131
- }
2132
- return elementsClient;
2133
- }
2134
-
2135
- // product-page.js
2136
- const client = await getElementsClient();
2137
- await client.injectProductElement([
2138
- { containerId: 'pdp-1', identifier: productId }
2139
- ]);
2140
-
2141
- // cart-page.js
2142
- const client = await getElementsClient();
2143
- const cartComponent = await client.injectCartElement('cart-container');
2144
- ```
2145
-
2146
- ---
2147
-
2148
- ## 🚨 Error Handling
2149
-
2150
- ### Initialization Errors
2151
-
2152
- ```js
2153
- try {
2154
- const client = await Elements('YOUR_API_KEY', {
2155
- env: 'production'
2156
- });
2157
- } catch (error) {
2158
- if (error.message.includes('Invalid API key')) {
2159
- console.error('Authentication failed');
2160
- } else if (error.message.includes('Network')) {
2161
- console.error('Network error - check connectivity');
2162
- } else {
2163
- console.error('SDK initialization failed:', error);
2164
- }
2165
- }
2166
- ```
2167
-
2168
- ### Action Errors
2169
-
2170
- All actions emit failure events with detailed error information:
2171
-
2172
- ```js
2173
- // Product loaded successfully
2174
- window.addEventListener('lce:actions.product_loaded', (event) => {
2175
- const { identifier, productData } = event.detail.data;
2176
- console.log(`Product ${identifier} loaded successfully`);
2177
- });
2178
-
2179
- // Cart action failure
2180
- window.addEventListener('lce:actions.cart_product_add_failed', (event) => {
2181
- const { identifiers, error } = event.detail.data;
2182
- console.error('Failed to add products:', error);
2183
-
2184
- // Show user-friendly message
2185
- showNotification('Could not add to cart. Please try again.', 'error');
2186
- });
2187
-
2188
- // Checkout failure
2189
- window.addEventListener('lce:actions.checkout_submit_failed', (event) => {
2190
- const { error, reason } = event.detail.data;
2191
- console.error('Checkout failed:', reason);
2192
-
2193
- // Handle specific errors
2194
- if (reason.includes('payment')) {
2195
- showNotification('Payment declined. Please check your card details.', 'error');
2196
- } else if (reason.includes('inventory')) {
2197
- showNotification('Some items are no longer available.', 'warning');
2198
- } else {
2199
- showNotification('Checkout failed. Please try again.', 'error');
2200
- }
2201
- });
2202
-
2203
- // Address validation failure
2204
- window.addEventListener('lce:actions.address_failed', (event) => {
2205
- const { error } = event.detail.data;
2206
- console.error('Address validation failed:', error);
2207
- showNotification('Please enter a valid address.', 'error');
2208
- });
2209
-
2210
- // Promo code failure
2211
- window.addEventListener('lce:actions.cart_promo_code_failed', (event) => {
2212
- const { code, error } = event.detail.data;
2213
- console.error(`Promo code ${code} failed:`, error);
2214
-
2215
- if (error.includes('expired')) {
2216
- showNotification('This promo code has expired.', 'warning');
2217
- } else if (error.includes('invalid')) {
2218
- showNotification('Invalid promo code.', 'error');
2219
- } else if (error.includes('minimum')) {
2220
- showNotification('Cart minimum not met for this promo.', 'warning');
2221
- }
2222
- });
2223
- ```
2224
-
2225
- ### Network Error Recovery
2226
-
2227
- ```js
2228
- let retryCount = 0;
2229
- const maxRetries = 3;
2230
-
2231
- async function addProductWithRetry(productParams) {
2232
- try {
2233
- await client.actions.cart.addProduct(productParams);
2234
- } catch (error) {
2235
- if (retryCount < maxRetries && error.message.includes('Network')) {
2236
- retryCount++;
2237
- console.log(`Retrying... Attempt ${retryCount}/${maxRetries}`);
2238
- setTimeout(() => addProductWithRetry(productParams), 1000 * retryCount);
2239
- } else {
2240
- console.error('Failed after retries:', error);
2241
- showNotification('Network error. Please check your connection.', 'error');
2242
- }
2243
- }
2244
- }
2245
- ```
2246
-
2247
- ### Global Error Handler
2248
-
2249
- ```js
2250
- // Listen to all failed events
2251
- window.addEventListener('lce:actions.cart_failed', handleError);
2252
- window.addEventListener('lce:actions.checkout_failed', handleError);
2253
- window.addEventListener('lce:actions.address_failed', handleError);
2254
- window.addEventListener('lce:actions.cart_product_add_failed', handleError);
2255
-
2256
- function handleError(event) {
2257
- const { error, context } = event.detail.data;
2258
-
2259
- // Log to error tracking service
2260
- if (window.Sentry) {
2261
- Sentry.captureException(error, {
2262
- tags: { sdk: 'liquid-commerce' },
2263
- extra: context
2264
- });
2265
- }
2266
-
2267
- // Show user notification
2268
- showNotification('Something went wrong. Please try again.', 'error');
2269
- }
2270
- ```
2271
-
2272
- ---
2273
-
2274
- ## ⚡ Performance & Best Practices
2275
-
2276
- ### Lazy Loading Components
2277
-
2278
- Only inject components when needed:
2279
-
2280
- ```js
2281
- // ❌ Don't inject all components upfront
2282
- await client.injectProductElement([/* 50 products */]);
2283
- await client.injectCartElement('cart');
2284
- await client.injectCheckoutElement('checkout');
2285
-
2286
- // ✅ Inject components as user navigates
2287
- // On product page:
2288
- await client.injectProductElement([{ containerId: 'pdp', identifier: productId }]);
2289
-
2290
- // On cart page (when user clicks cart):
2291
- await client.injectCartElement('cart');
2292
-
2293
- // On checkout (when user proceeds):
2294
- await client.injectCheckoutElement('checkout');
2295
- ```
2296
-
2297
- ### Reuse Client Instance
2298
-
2299
- Initialize once, use everywhere:
2300
-
2301
- ```js
2302
- // ❌ Don't create multiple clients
2303
- // page1.js
2304
- const client1 = await Elements('KEY', { env: 'production' });
2305
- // page2.js
2306
- const client2 = await Elements('KEY', { env: 'production' });
2307
-
2308
- // ✅ Create once, reuse
2309
- // app.js
2310
- window.lceClient = await Elements('KEY', { env: 'production' });
2311
-
2312
- // page1.js
2313
- const client = window.lceClient;
2314
- await client.injectProductElement([...]);
2315
-
2316
- // page2.js
2317
- const client = window.lceClient;
2318
- await client.injectCartElement('cart');
2319
- ```
2320
-
2321
- ### Batch Product Injections
2322
-
2323
- Group product injections together:
2324
-
2325
- ```js
2326
- // ❌ Don't inject products one by one
2327
- await client.injectProductElement([{ containerId: 'p1', identifier: 'id1' }]);
2328
- await client.injectProductElement([{ containerId: 'p2', identifier: 'id2' }]);
2329
- await client.injectProductElement([{ containerId: 'p3', identifier: 'id3' }]);
2330
-
2331
- // ✅ Inject all products at once
2332
- await client.injectProductElement([
2333
- { containerId: 'p1', identifier: 'id1' },
2334
- { containerId: 'p2', identifier: 'id2' },
2335
- { containerId: 'p3', identifier: 'id3' }
2336
- ]);
2337
- ```
2338
-
2339
- ### Optimize Event Listeners
2340
-
2341
- Use event delegation instead of multiple listeners:
2342
-
2343
- ```js
2344
- // ❌ Don't listen to every event
2345
- window.addEventListener('lce:actions.product_loaded', handler);
2346
- window.addEventListener('lce:actions.product_add_to_cart', handler);
2347
- window.addEventListener('lce:actions.cart_updated', handler);
2348
- // ... 20 more listeners
2349
-
2350
- // ✅ Use consolidated listeners
2351
- window.elements.onAllActions((data, metadata) => {
2352
- switch (metadata.eventName) {
2353
- case 'lce:actions.product_loaded':
2354
- handleProductLoad(data);
2355
- break;
2356
- case 'lce:actions.product_add_to_cart':
2357
- handleAddToCart(data);
2358
- break;
2359
- case 'lce:actions.cart_updated':
2360
- handleCartUpdate(data);
2361
- break;
2362
- }
2363
- });
2364
- ```
2365
-
2366
- ### Defer Non-Critical Operations
2367
-
2368
- Load SDK after critical page content:
2369
-
2370
- ```html
2371
- <!-- ❌ Don't load SDK in <head> -->
2372
- <head>
2373
- <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
2374
- </head>
2375
-
2376
- <!-- ✅ Load SDK with defer or at end of body -->
2377
- <head>
2378
- <script defer src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
2379
- </head>
2380
-
2381
- <!-- Or -->
2382
- <body>
2383
- <!-- Your page content -->
2384
- <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
2385
- </body>
49
+ <div id="product"></div>
2386
50
  ```
2387
51
 
2388
- ### Use Auto-Init for Simple Cases
52
+ ### NPM (Programmatic)
2389
53
 
2390
- Auto-init is optimized for performance:
2391
-
2392
- ```html
2393
- <!-- ✅ Auto-init is the fastest way for simple setups -->
2394
- <div data-lce-product="00619947000020"></div>
2395
- <div data-lce-product="00832889005513"></div>
2396
-
2397
- <script
2398
- data-liquid-commerce-elements
2399
- data-token="YOUR_API_KEY"
2400
- data-env="production"
2401
- src="https://assets-elements.liquidcommerce.us/all/elements.js"
2402
- ></script>
54
+ ```bash
55
+ npm install @liquidcommerce/elements-sdk
2403
56
  ```
2404
57
 
2405
- ### Avoid Unnecessary Re-renders
2406
-
2407
- Don't repeatedly inject the same component:
2408
-
2409
- ```js
2410
- // ❌ Don't re-inject on every state change
2411
- function updateProduct() {
2412
- setProductId(newId);
2413
- await client.injectProductElement([{ containerId: 'pdp', identifier: newId }]);
2414
- }
2415
-
2416
- // ✅ Components update automatically on state changes
2417
- // Just inject once
2418
- useEffect(() => {
2419
- client.injectProductElement([{ containerId: 'pdp', identifier: productId }]);
2420
- }, []); // Empty deps - inject once
2421
-
2422
- // Product will auto-update when you call actions
2423
- await client.actions.cart.addProduct([...]);
2424
- ```
58
+ ```javascript
59
+ import { Elements } from '@liquidcommerce/elements-sdk';
2425
60
 
2426
- ### Cache Frequently Accessed Data
61
+ // Elements() resolves to `null` if initialization fails — it never throws.
62
+ const client = await Elements('YOUR_API_KEY', { env: 'production' });
2427
63
 
2428
- ```js
2429
- // ❌ Don't repeatedly fetch the same data
2430
- async function showCartTotal() {
2431
- const cart = await client.actions.cart.getDetails();
2432
- return cart.amounts.total;
64
+ if (client) {
65
+ await client.injectProductElement([
66
+ { containerId: 'product', identifier: '00619947000020' }
67
+ ]);
2433
68
  }
2434
-
2435
- // ✅ Use UI helpers that auto-update
2436
- client.ui.cartSubtotal('cart-total-display');
2437
- client.ui.cartItemsCount('cart-count-display');
2438
-
2439
- // Or cache and listen to updates
2440
- let cachedCart = await client.actions.cart.getDetails();
2441
- window.addEventListener('lce:actions.cart_updated', (event) => {
2442
- cachedCart = event.detail.data.current;
2443
- });
2444
69
  ```
2445
70
 
2446
- ### Use CDN for Production
71
+ ## Core Concepts (Short)
2447
72
 
2448
- Always use CDN in production for optimal caching:
73
+ - **Web Components + Shadow DOM** for framework-agnostic UI and style isolation
74
+ - **Declarative setup** via HTML data attributes
75
+ - **Programmatic setup** via `Elements()` client for dynamic injection
76
+ - **Events** for analytics and custom UI
77
+ - **Actions API** for cart/checkout control
2449
78
 
2450
- ```js
2451
- // ✅ CDN (recommended)
2452
- <script src="https://assets-elements.liquidcommerce.us/all/elements.js"></script>
2453
-
2454
- // ❌ Don't self-host unless necessary
2455
- <script src="/static/elements.js"></script>
2456
- ```
79
+ ## Components
2457
80
 
2458
- ### Minimize Theme Complexity
81
+ - **Product**: Images, variants, fulfillment, add-to-cart
82
+ - **Cart**: Drawer with items, totals, promo codes
83
+ - **Checkout**: Drawer or hosted page with full purchase flow
84
+ - **Address**: Delivery location capture
85
+ - **Product List**: Filterable, searchable grids
2459
86
 
2460
- Simpler themes = faster rendering:
87
+ ## Key Methods (High Level)
2461
88
 
2462
- ```js
2463
- // Don't override every style property
2464
- customTheme: {
2465
- global: {
2466
- colors: { /* 20 color overrides */ },
2467
- typography: { /* 15 typography overrides */ },
2468
- shadows: { /* 10 shadow overrides */ },
2469
- // ... 100 more overrides
2470
- }
2471
- }
89
+ - `injectProductElement`, `injectCartElement`, `injectCheckoutElement`, `injectAddressElement`
90
+ - `injectProductList`, `injectProductListFilters`, `injectProductListSearch`
91
+ - `ui.cartButton`, `ui.floatingCartButton`, `ui.cartSubtotal`, `ui.cartItemsCount`
92
+ - `actions.product`, `actions.cart`, `actions.checkout`, `actions.address`
93
+ - `getInjectedComponents`, `destroy`
2472
94
 
2473
- // ✅ Override only what's necessary
2474
- customTheme: {
2475
- global: {
2476
- colors: {
2477
- primary: '#007bff',
2478
- secondary: '#6c757d'
2479
- }
2480
- }
2481
- }
95
+ ```javascript
96
+ // Example: add a product and open cart
97
+ await window.LiquidCommerce.elements.actions.cart.addProduct([
98
+ { identifier: '00619947000020', fulfillmentType: 'shipping', quantity: 1 }
99
+ ], true);
2482
100
  ```
2483
101
 
2484
- ### Monitor Performance
2485
-
2486
- Track SDK performance in production:
102
+ ## Events (High Level)
2487
103
 
2488
- ```js
2489
- // Measure initialization time
2490
- const start = performance.now();
2491
- const client = await Elements('YOUR_API_KEY', { env: 'production' });
2492
- console.log(`SDK initialized in ${performance.now() - start}ms`);
104
+ Listen for SDK events to drive analytics or custom UI:
2493
105
 
2494
- // Track component load times
106
+ ```javascript
2495
107
  window.addEventListener('lce:actions.product_loaded', (event) => {
2496
- const { loadTime } = event.detail.metadata;
2497
- console.log(`Product loaded in ${loadTime}ms`);
2498
-
2499
- // Send to analytics
2500
- analytics.track('SDK Component Load', {
2501
- component: 'product',
2502
- duration: loadTime
2503
- });
108
+ console.log('Loaded:', event.detail.data.identifier);
2504
109
  });
2505
- ```
2506
-
2507
- ### Production Checklist
2508
-
2509
- Before going live:
2510
-
2511
- - ✅ Set `env: 'production'`
2512
- - ✅ Set `debugMode: 'none'` (or omit)
2513
- - ✅ Use CDN script URL
2514
- - ✅ Pin to specific version (optional but recommended)
2515
- - ✅ Configure proxy if using ad blockers
2516
- - ✅ Test error handling
2517
- - ✅ Verify event tracking
2518
- - ✅ Check cart persistence
2519
- - ✅ Test on target browsers
2520
- - ✅ Measure performance metrics
2521
-
2522
- **Production-ready init:**
2523
110
 
2524
- ```js
2525
- const client = await Elements('YOUR_PRODUCTION_API_KEY', {
2526
- env: 'production',
2527
- debugMode: 'none',
2528
- customTheme: { /* minimal overrides */ },
2529
- proxy: { baseUrl: 'https://yourdomain.com/api/proxy' }
111
+ window.addEventListener('lce:actions.checkout_submit_completed', (event) => {
112
+ console.log('Order:', event.detail.data.orderNumber);
2530
113
  });
2531
114
  ```
2532
115
 
2533
- **📖 For debugging and troubleshooting:** See [`docs/TROUBLESHOOTING.md`](docs/TROUBLESHOOTING.md) for comprehensive problem-solving guide.
2534
-
2535
- ---
2536
-
2537
- ## 🔒 Proxy Configuration
116
+ ## Theming
2538
117
 
2539
- Route API requests through your server to avoid ad blockers:
2540
-
2541
- ```js
118
+ ```javascript
2542
119
  const client = await Elements('YOUR_API_KEY', {
2543
120
  env: 'production',
2544
- proxy: {
2545
- baseUrl: 'https://yourdomain.com/api/liquidcommerce',
2546
- headers: {
2547
- 'X-Custom-Header': 'value'
121
+ customTheme: {
122
+ global: {
123
+ theme: {
124
+ primaryColor: '#007bff',
125
+ buttonCornerRadius: '8px'
126
+ }
2548
127
  }
2549
128
  }
2550
129
  });
2551
130
  ```
2552
131
 
2553
- The SDK automatically handles routing and required headers. See [`docs/PROXY.md`](docs/PROXY.md) for complete proxy setup guide with Next.js examples.
2554
-
2555
- ## 📚 Documentation
2556
-
2557
- **📖 Complete Documentation:**
132
+ ## Integrations
2558
133
 
2559
- - **[Documentation Index](docs/DOCUMENTATION_INDEX.md)** - Complete guide to all documentation
2560
- - **[Configuration Reference](docs/CONFIGURATION.md)** - All configuration options with TypeScript types
2561
- - **[Theming Guide](docs/THEMING.md)** - Complete customization reference
2562
- - **[Actions Reference](docs/ACTIONS.md)** - Programmatic control with business use cases
2563
- - **[Events Reference](docs/EVENTS.md)** - Event system and tracking guide
2564
- - **[Troubleshooting Guide](docs/TROUBLESHOOTING.md)** - Common issues and solutions
2565
- - **[Browser Support](docs/BROWSER_SUPPORT.md)** - Detailed browser compatibility
2566
- - **[Proxy Setup](docs/PROXY.md)** - Ad blocker avoidance configuration
134
+ Works with any framework. See:
2567
135
 
2568
- ---
2569
-
2570
- ## 🏷️ Versioning
136
+ - [React](./docs/v1/integration/react.md)
137
+ - [Next.js](./docs/v1/integration/nextjs.md)
138
+ - [Vue](./docs/v1/integration/vue.md)
139
+ - [Angular](./docs/v1/integration/angular.md)
140
+ - [Laravel](./docs/v1/integration/laravel.md)
141
+ - [Vanilla JS](./docs/v1/integration/vanilla-js.md)
142
+ - [Proxy Setup](./docs/v1/integration/proxy-setup.md)
2571
143
 
2572
- This project uses Semantic Versioning. Two CDN environments are available:
144
+ ## Documentation (v1)
2573
145
 
2574
- - **Production:** `https://assets-elements.liquidcommerce.us/all/elements.js` (stable)
2575
- - **Beta:** `https://assets-elements.liquidcommerce.us/all/beta/elements.js` (pre-release)
146
+ - [Start Here](./docs/v1/README.md)
147
+ - [Getting Started](./docs/v1/getting-started/installation.md)
148
+ - [Guides](./docs/v1/guides/)
149
+ - [Accessibility](./docs/v1/guides/accessibility.md)
150
+ - [API Reference](./docs/v1/api/)
151
+ - [Examples](./docs/v1/examples/)
152
+ - [Reference](./docs/v1/reference/)
2576
153
 
2577
- ## 💬 Support
154
+ ## Accessibility
2578
155
 
2579
- If you need help with your API key, environment selection, or implementation, contact your LiquidCommerce representative.
156
+ Elements target WCAG 2.1 AA out of the box: single-tab-stop keyboard groups with arrow-key
157
+ navigation, managed focus for every overlay, and screen-reader announcements for content that
158
+ changes without navigation. Colour contrast depends on the theme you supply — the SDK renders your
159
+ colours as given.
2580
160
 
2581
- ---
161
+ See the [Accessibility Guide](./docs/v1/guides/accessibility.md) for the keyboard map, the list of
162
+ announcements, and what your page is responsible for.
2582
163
 
2583
- <div align="center">
164
+ ## Browser Support
2584
165
 
2585
- **Built with ❤️ by the LiquidCommerce Team**
166
+ Chrome 66+, Firefox 60+, Safari 12+, Edge 79+.
167
+ See [Browser Support](./docs/v1/reference/browser-support.md) for details.
2586
168
 
2587
- [Actions Reference](docs/ACTIONS.md) • [Events Guide](docs/EVENTS.md) • [Browser Support](docs/BROWSER_SUPPORT.md) • [Proxy Setup](docs/PROXY.md)
169
+ ## Support
2588
170
 
2589
- </div>
171
+ Contact your LiquidCommerce representative for assistance.