@liquidcommerce/elements-sdk 2.7.1 → 2.7.2

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.
@@ -1,136 +1,1764 @@
1
1
  # Events
2
2
 
3
- The SDK emits events for user actions and state changes. Listen on `window` using the `lce:actions.*` namespace.
3
+ The SDK emits browser events for user actions and state changes. Listen on `window` using `lce:actions.*` and `lce:forms.*`.
4
4
 
5
5
  ## Event shape
6
+
7
+ All SDK events are native `CustomEvent` objects. The payload lives in `event.detail`:
8
+
9
+ ```ts
10
+ export interface IEventMetadata {
11
+ eventId: string;
12
+ namespace: 'actions' | 'forms';
13
+ event: string;
14
+ originalEvent: string;
15
+ actionNamespace?: 'address' | 'product' | 'cart' | 'checkout' | 'other';
16
+ timestamp: number;
17
+ }
18
+
19
+ export interface IEnhancedEventData<T> {
20
+ data: T;
21
+ metadata: IEventMetadata;
22
+ }
23
+ ```
24
+
6
25
  ```js
7
26
  window.addEventListener('lce:actions.event_name', (event) => {
8
- const { namespace, event: eventName, timestamp, id, data } = event.detail;
27
+ const { data, metadata } = event.detail;
28
+ });
29
+ ```
30
+
31
+ **TypeScript interfaces:** The interface names used below match the SDK type definitions. You can inspect them in your install at `node_modules/@liquidcommerce/elements-sdk/dist/types/core/pubsub/interfaces/*`.
32
+
33
+ ## Namespaces
34
+
35
+ - `lce:actions.*` - User actions and state changes
36
+ - `lce:forms.*` - Form field interactions (checkout)
37
+ - `lce:actions` - All action events (namespace listener)
38
+ - `lce:forms` - All form events (namespace listener)
39
+
40
+ Example: listen to every action event:
41
+
42
+ ```js
43
+ window.addEventListener('lce:actions', (event) => {
44
+ const { metadata } = event.detail;
45
+ console.log('Action event:', metadata.event);
9
46
  });
10
47
  ```
11
48
 
12
49
  ## Client lifecycle
13
- - `lce:actions.client_ready`
14
- Fired when the SDK is initialized and safe to use.
50
+
51
+ ### `lce:actions.client_ready`
52
+
53
+ Fired once when the SDK is initialized and safe to use.
54
+
55
+ **Data shape (TypeScript)**
56
+
57
+ ```ts
58
+ export interface IElementsClientIsReadyEventData {
59
+ isReady: boolean;
60
+ message: string;
61
+ timestamp: number;
62
+ version?: string;
63
+ }
64
+ ```
65
+
66
+ **Example**
15
67
 
16
68
  ```js
17
69
  window.addEventListener('lce:actions.client_ready', (event) => {
18
- const { isReady, version, timestamp } = event.detail.data;
70
+ const { data } = event.detail;
71
+ if (data.isReady) {
72
+ console.log('Elements SDK ready', data.version);
73
+ }
19
74
  });
20
75
  ```
21
76
 
22
77
  ## Product events
23
- - `lce:actions.product_loaded`
24
- Product data loaded into the component.
25
- - `lce:actions.product_add_to_cart`
26
- User clicked Add to Cart.
27
- - `lce:actions.product_size_changed`
28
- User changed the selected size.
29
- - `lce:actions.product_fulfillment_type_changed`
30
- User switched fulfillment type (shipping/onDemand).
31
- - `lce:actions.product_fulfillment_changed`
32
- Retailer selection changed.
33
- - `lce:actions.product_quantity_increase`
34
- User increased quantity.
35
- - `lce:actions.product_quantity_decrease`
36
- User decreased quantity.
78
+
79
+ ### `lce:actions.product_loaded`
80
+
81
+ Product data finished loading into a product component.
82
+
83
+ **Data shape (TypeScript)**
84
+
85
+ ```ts
86
+ export type FulfillmentType = 'onDemand' | 'shipping';
87
+
88
+ export interface IProductLoadedEventData {
89
+ identifier: string;
90
+ selectedSizeId: string | null;
91
+ selectedFulfillmentType: FulfillmentType;
92
+ selectedFulfillmentId: string | null;
93
+ productHasAvailability: boolean;
94
+ fulfillmentHasAvailability: boolean;
95
+ sizes: Record<string, IProductSizeEventData>;
96
+
97
+ id: string;
98
+ name: string;
99
+ description: string;
100
+ htmlDescription: string;
101
+ images: string[];
102
+ brand: string;
103
+ region: string;
104
+ country: string;
105
+ material: string;
106
+ abv: string;
107
+ proof: string;
108
+ age: string;
109
+ color: string;
110
+ flavor: string;
111
+ variety: string;
112
+ appellation: string;
113
+ vintage: string;
114
+ tastingNotes: string;
115
+ catPath: string;
116
+ category: string;
117
+ classification: string;
118
+ type: string;
119
+ subType: string;
120
+ salsifyGrouping: string;
121
+ noAvailabilityPrice: number;
122
+ }
123
+
124
+ export interface IProductSizeEventData {
125
+ id: string;
126
+ upc: string;
127
+ size: string;
128
+ pack: boolean;
129
+ packDesc: string;
130
+ container: string;
131
+ containerType: string;
132
+ image: string;
133
+ uom: string;
134
+ volume: string;
135
+ maxQuantityPerOrder: number;
136
+ attributes: IProductSizeAttributes;
137
+ onDemandFulfillments: Record<string, IProductFulfillmentEventData>;
138
+ shippingFulfillments: Record<string, IProductFulfillmentEventData>;
139
+ }
140
+
141
+ export interface IProductSizeAttributes {
142
+ presale: IProductPresale;
143
+ engraving: IProductSizeEngraving;
144
+ }
145
+
146
+ export interface IProductSizeEngraving {
147
+ maxLines: number;
148
+ maxCharsPerLine: number;
149
+ fee: number;
150
+ location: string;
151
+ }
152
+
153
+ export interface IProductPresale {
154
+ canPurchaseOn: string | null;
155
+ estimatedShipBy: string | null;
156
+ isActive: boolean;
157
+ language: string;
158
+ }
159
+
160
+ export interface IProductFulfillmentEventData {
161
+ id: string;
162
+ type: FulfillmentType;
163
+ doesAllowGiftCards: boolean;
164
+ doesAllowPromos: boolean;
165
+ expectation: string;
166
+ engravingExpectation: string;
167
+ fee: number;
168
+ timezone: string;
169
+ hourStatus: IProductFulfillmentHourStatus;
170
+ retailerName: string;
171
+ retailerAddress: IRetailerAddress;
172
+ retailerAddressFormatted: string;
173
+ variant: IProductVariant;
174
+ }
175
+
176
+ export interface IProductFulfillmentHourStatus {
177
+ isOpen: boolean;
178
+ openTime: string;
179
+ isClosed: boolean;
180
+ closeTime: string;
181
+ }
182
+
183
+ export interface IProductVariant {
184
+ retailerId: string;
185
+ shippingFulfillmentId: string;
186
+ onDemandFulfillmentId: string;
187
+ isEngravable: boolean;
188
+ partNumber: string;
189
+ price: number;
190
+ stock: number;
191
+ }
192
+
193
+ export type IRetailerAddress = IAddressAddress & IAddressCoordinates;
194
+
195
+ export interface IAddressAddress {
196
+ one: string;
197
+ two: string;
198
+ city: string;
199
+ state: string;
200
+ zip: string;
201
+ country: string;
202
+ }
203
+
204
+ export interface IAddressCoordinates {
205
+ latitude: number;
206
+ longitude: number;
207
+ }
208
+ ```
209
+
210
+ **Example**
37
211
 
38
212
  ```js
39
213
  window.addEventListener('lce:actions.product_loaded', (event) => {
40
- const { identifier, name, price } = event.detail.data;
214
+ const { data } = event.detail;
215
+ console.log(`Loaded ${data.name} (${data.identifier})`);
216
+ });
217
+ ```
218
+
219
+ ### `lce:actions.product_add_to_cart`
220
+
221
+ User triggered add-to-cart from a product component. Use cart events to confirm success or failure.
222
+
223
+ **Data shape (TypeScript)**
224
+
225
+ ```ts
226
+ export interface IProductAddToCartEventData {
227
+ identifier: string;
228
+ fulfillmentId: string;
229
+ partNumber: string;
230
+ quantity: number;
231
+ engravingLines?: string[];
232
+ }
233
+ ```
234
+
235
+ **Example**
236
+
237
+ ```js
238
+ window.addEventListener('lce:actions.product_add_to_cart', (event) => {
239
+ const { data } = event.detail;
240
+ gtag('event', 'add_to_cart_click', { item_id: data.identifier, quantity: data.quantity });
241
+ });
242
+ ```
243
+
244
+ ### `lce:actions.product_size_changed`
245
+
246
+ User changed the selected size.
247
+
248
+ **Data shape (TypeScript)**
249
+
250
+ ```ts
251
+ export interface IProductSizeChangedEventData {
252
+ identifier: string;
253
+ selectedSizeId: string;
254
+ selectedSize: string;
255
+ previousSizeId: string;
256
+ previousSize: string;
257
+ }
258
+ ```
259
+
260
+ **Example**
261
+
262
+ ```js
263
+ window.addEventListener('lce:actions.product_size_changed', (event) => {
264
+ const { data } = event.detail;
265
+ console.log('Size changed to', data.selectedSize);
266
+ });
267
+ ```
268
+
269
+ ### `lce:actions.product_fulfillment_type_changed`
270
+
271
+ User switched fulfillment type (for example shipping vs onDemand).
272
+
273
+ **Data shape (TypeScript)**
274
+
275
+ ```ts
276
+ export type FulfillmentType = 'onDemand' | 'shipping';
277
+
278
+ export interface IProductFulfillmentTypeChangedEventData {
279
+ identifier: string;
280
+ selectedFulfillmentType: FulfillmentType;
281
+ selectedFulfillmentId: string | null;
282
+ previousFulfillmentType: FulfillmentType;
283
+ previousFulfillmentId: string | null;
284
+ fulfillmentHasAvailability: boolean;
285
+ }
286
+ ```
287
+
288
+ **Example**
289
+
290
+ ```js
291
+ window.addEventListener('lce:actions.product_fulfillment_type_changed', (event) => {
292
+ const { data } = event.detail;
293
+ console.log('Fulfillment type:', data.selectedFulfillmentType);
294
+ });
295
+ ```
296
+
297
+ ### `lce:actions.product_fulfillment_changed`
298
+
299
+ User selected a different fulfillment option or retailer.
300
+
301
+ **Data shape (TypeScript)**
302
+
303
+ ```ts
304
+ export type FulfillmentType = 'onDemand' | 'shipping';
305
+
306
+ export interface IProductFulfillmentChangedEventData {
307
+ identifier: string;
308
+ selectedFulfillmentId: string;
309
+ selectedFulfillmentType: FulfillmentType;
310
+ previousFulfillmentId: string;
311
+ previousFulfillmentType: FulfillmentType;
312
+ }
313
+ ```
314
+
315
+ **Example**
316
+
317
+ ```js
318
+ window.addEventListener('lce:actions.product_fulfillment_changed', (event) => {
319
+ const { data } = event.detail;
320
+ console.log('Fulfillment changed:', data.selectedFulfillmentId);
321
+ });
322
+ ```
323
+
324
+ ### `lce:actions.product_quantity_increase`
325
+
326
+ Product quantity increased.
327
+
328
+ **Data shape (TypeScript)**
329
+
330
+ ```ts
331
+ export interface IProductQuantityChangedEventData {
332
+ identifier: string;
333
+ quantity: number;
334
+ previousQuantity: number;
335
+ }
336
+ ```
337
+
338
+ **Example**
339
+
340
+ ```js
341
+ window.addEventListener('lce:actions.product_quantity_increase', (event) => {
342
+ const { data } = event.detail;
343
+ console.log('Quantity increased to', data.quantity);
344
+ });
345
+ ```
346
+
347
+ ### `lce:actions.product_quantity_decrease`
348
+
349
+ Product quantity decreased.
350
+
351
+ **Data shape (TypeScript)**
352
+
353
+ ```ts
354
+ export interface IProductQuantityChangedEventData {
355
+ identifier: string;
356
+ quantity: number;
357
+ previousQuantity: number;
358
+ }
359
+ ```
360
+
361
+ **Example**
362
+
363
+ ```js
364
+ window.addEventListener('lce:actions.product_quantity_decrease', (event) => {
365
+ const { data } = event.detail;
366
+ console.log('Quantity decreased to', data.quantity);
41
367
  });
42
368
  ```
43
369
 
44
370
  ## Address events
45
- - `lce:actions.address_updated`
46
- Address successfully set or changed.
47
- - `lce:actions.address_cleared`
48
- Address removed.
49
- - `lce:actions.address_failed`
50
- Address set failed (validation, geocode, etc.).
371
+
372
+ ### `lce:actions.address_updated`
373
+
374
+ Address successfully set or changed.
375
+
376
+ **Data shape (TypeScript)**
377
+
378
+ ```ts
379
+ export interface IAddressActionEventData {
380
+ googlePlacesId: string;
381
+ formattedAddress: string;
382
+ address: IAddressAddress;
383
+ coordinates: IAddressCoordinates;
384
+ }
385
+
386
+ export interface IAddressAddress {
387
+ one: string;
388
+ two: string;
389
+ city: string;
390
+ state: string;
391
+ zip: string;
392
+ country: string;
393
+ }
394
+
395
+ export interface IAddressCoordinates {
396
+ latitude: number;
397
+ longitude: number;
398
+ }
399
+ ```
400
+
401
+ **Example**
51
402
 
52
403
  ```js
53
404
  window.addEventListener('lce:actions.address_updated', (event) => {
54
- const { formattedAddress } = event.detail.data;
405
+ const { data } = event.detail;
406
+ console.log('Address set:', data.formattedAddress);
407
+ });
408
+ ```
409
+
410
+ ### `lce:actions.address_cleared`
411
+
412
+ Address removed.
413
+
414
+ **Data shape (TypeScript)**
415
+
416
+ ```ts
417
+ export type AddressClearedEventData = boolean;
418
+ ```
419
+
420
+ **Example**
421
+
422
+ ```js
423
+ window.addEventListener('lce:actions.address_cleared', () => {
424
+ console.log('Address cleared');
425
+ });
426
+ ```
427
+
428
+ ### `lce:actions.address_failed`
429
+
430
+ Address set failed (validation, geocode, etc.).
431
+
432
+ **Data shape (TypeScript)**
433
+
434
+ ```ts
435
+ export interface IAddressFailedEventData {
436
+ googlePlacesId: string;
437
+ formattedAddress: string;
438
+ address: IAddressAddress;
439
+ coordinates: IAddressCoordinates;
440
+ error: string;
441
+ }
442
+
443
+ export interface IAddressAddress {
444
+ one: string;
445
+ two: string;
446
+ city: string;
447
+ state: string;
448
+ zip: string;
449
+ country: string;
450
+ }
451
+
452
+ export interface IAddressCoordinates {
453
+ latitude: number;
454
+ longitude: number;
455
+ }
456
+ ```
457
+
458
+ **Example**
459
+
460
+ ```js
461
+ window.addEventListener('lce:actions.address_failed', (event) => {
462
+ const { data } = event.detail;
463
+ console.error('Address error:', data.error);
55
464
  });
56
465
  ```
57
466
 
58
467
  ## Cart events
59
- - `lce:actions.cart_loaded`
60
- Cart state loaded.
61
- - `lce:actions.cart_opened`
62
- Cart drawer opened.
63
- - `lce:actions.cart_closed`
64
- Cart drawer closed.
65
- - `lce:actions.cart_updated`
66
- Cart totals/items changed.
67
- - `lce:actions.cart_item_added`
68
- Item added to cart.
69
- - `lce:actions.cart_item_removed`
70
- Item removed from cart.
71
- - `lce:actions.cart_item_quantity_increase`
72
- Cart item quantity increased.
73
- - `lce:actions.cart_item_quantity_decrease`
74
- Cart item quantity decreased.
75
- - `lce:actions.cart_promo_code_applied`
76
- Promo code applied to cart.
77
- - `lce:actions.cart_promo_code_removed`
78
- Promo code removed from cart.
79
- - `lce:actions.cart_promo_code_failed`
80
- Promo code failed validation.
81
- - `lce:actions.cart_product_add_success`
82
- Programmatic add-to-cart succeeded.
83
- - `lce:actions.cart_product_add_failed`
84
- Programmatic add-to-cart failed.
468
+
469
+ ### `lce:actions.cart_loaded`
470
+
471
+ Cart state loaded or synced.
472
+
473
+ **Data shape (TypeScript)**
474
+
475
+ ```ts
476
+ export type FulfillmentType = 'onDemand' | 'shipping';
477
+
478
+ export interface IBaseCartEventData {
479
+ cartId: string;
480
+ promoCodeDiscount: number | null;
481
+ subtotal: number;
482
+ itemCount: number;
483
+ items: Record<string, ICartItem>;
484
+ retailers: Record<string, ICartRetailer>;
485
+ location: {
486
+ placesId: string;
487
+ formattedAddress: string;
488
+ address: IAddressAddress;
489
+ coordinates: IAddressCoordinates;
490
+ } | null;
491
+ }
492
+
493
+ export interface ICartItem {
494
+ id: string;
495
+ variantId: string;
496
+ liquidId: string;
497
+ retailerId: string;
498
+ partNumber: string;
499
+ fulfillmentId: string;
500
+ upc: string;
501
+ sku: string;
502
+ salsifyGrouping: string;
503
+ catPath: string;
504
+ volume: string;
505
+ uom: string;
506
+ pack: boolean;
507
+ packDesc: string;
508
+ container: string;
509
+ containerType: string;
510
+ name: string;
511
+ brand: string;
512
+ size: string;
513
+ price: number;
514
+ quantity: number;
515
+ maxQuantity: number;
516
+ unitPrice: number;
517
+ mainImage: string;
518
+ attributes: ICartItemAttributes;
519
+ }
520
+
521
+ export interface ICartItemAttributes {
522
+ engraving: ICartItemEngraving;
523
+ presale: IProductPresale;
524
+ }
525
+
526
+ export interface ICartItemEngraving {
527
+ isEngravable: boolean;
528
+ hasEngraving: boolean;
529
+ fee: number;
530
+ maxCharsPerLine: number;
531
+ maxLines: number;
532
+ location: string;
533
+ lines: string[];
534
+ }
535
+
536
+ export interface IProductPresale {
537
+ canPurchaseOn: string | null;
538
+ estimatedShipBy: string | null;
539
+ isActive: boolean;
540
+ language: string;
541
+ }
542
+
543
+ export interface ICartRetailer {
544
+ id: string;
545
+ name: string;
546
+ subtotal: number;
547
+ itemsQuantity: number;
548
+ fulfillments: Record<string, ICartFulfillment>;
549
+ }
550
+
551
+ export interface ICartFulfillment {
552
+ id: string;
553
+ canEngrave: boolean;
554
+ type: FulfillmentType;
555
+ expectation: string;
556
+ engravingExpectation: string;
557
+ itemIds: string[];
558
+ subtotal: number;
559
+ hasUnmetMinimumPurchaseAmount: boolean;
560
+ minimumPurchaseAmount: number;
561
+ }
562
+
563
+ export interface IAddressAddress {
564
+ one: string;
565
+ two: string;
566
+ city: string;
567
+ state: string;
568
+ zip: string;
569
+ country: string;
570
+ }
571
+
572
+ export interface IAddressCoordinates {
573
+ latitude: number;
574
+ longitude: number;
575
+ }
576
+ ```
577
+
578
+ **Example**
579
+
580
+ ```js
581
+ window.addEventListener('lce:actions.cart_loaded', (event) => {
582
+ const { data } = event.detail;
583
+ console.log(`Cart ${data.cartId} has ${data.itemCount} items`);
584
+ });
585
+ ```
586
+
587
+ ### `lce:actions.cart_opened`
588
+
589
+ Cart drawer opened.
590
+
591
+ **Data shape (TypeScript)**
592
+
593
+ ```ts
594
+ export type CartOpenedEventData = boolean;
595
+ ```
596
+
597
+ **Example**
598
+
599
+ ```js
600
+ window.addEventListener('lce:actions.cart_opened', () => {
601
+ document.body.classList.add('cart-open');
602
+ });
603
+ ```
604
+
605
+ ### `lce:actions.cart_closed`
606
+
607
+ Cart drawer closed.
608
+
609
+ **Data shape (TypeScript)**
610
+
611
+ ```ts
612
+ export type CartClosedEventData = boolean;
613
+ ```
614
+
615
+ **Example**
616
+
617
+ ```js
618
+ window.addEventListener('lce:actions.cart_closed', () => {
619
+ document.body.classList.remove('cart-open');
620
+ });
621
+ ```
622
+
623
+ ### `lce:actions.cart_updated`
624
+
625
+ Cart totals/items changed.
626
+
627
+ **Data shape (TypeScript)**
628
+
629
+ ```ts
630
+ export interface ICartUpdatedEventData {
631
+ previous: IBaseCartEventData;
632
+ current: IBaseCartEventData;
633
+ }
634
+
635
+ export type FulfillmentType = 'onDemand' | 'shipping';
636
+
637
+ export interface IBaseCartEventData {
638
+ cartId: string;
639
+ promoCodeDiscount: number | null;
640
+ subtotal: number;
641
+ itemCount: number;
642
+ items: Record<string, ICartItem>;
643
+ retailers: Record<string, ICartRetailer>;
644
+ location: {
645
+ placesId: string;
646
+ formattedAddress: string;
647
+ address: IAddressAddress;
648
+ coordinates: IAddressCoordinates;
649
+ } | null;
650
+ }
651
+
652
+ export interface ICartItem {
653
+ id: string;
654
+ variantId: string;
655
+ liquidId: string;
656
+ retailerId: string;
657
+ partNumber: string;
658
+ fulfillmentId: string;
659
+ upc: string;
660
+ sku: string;
661
+ salsifyGrouping: string;
662
+ catPath: string;
663
+ volume: string;
664
+ uom: string;
665
+ pack: boolean;
666
+ packDesc: string;
667
+ container: string;
668
+ containerType: string;
669
+ name: string;
670
+ brand: string;
671
+ size: string;
672
+ price: number;
673
+ quantity: number;
674
+ maxQuantity: number;
675
+ unitPrice: number;
676
+ mainImage: string;
677
+ attributes: ICartItemAttributes;
678
+ }
679
+
680
+ export interface ICartItemAttributes {
681
+ engraving: ICartItemEngraving;
682
+ presale: IProductPresale;
683
+ }
684
+
685
+ export interface ICartItemEngraving {
686
+ isEngravable: boolean;
687
+ hasEngraving: boolean;
688
+ fee: number;
689
+ maxCharsPerLine: number;
690
+ maxLines: number;
691
+ location: string;
692
+ lines: string[];
693
+ }
694
+
695
+ export interface IProductPresale {
696
+ canPurchaseOn: string | null;
697
+ estimatedShipBy: string | null;
698
+ isActive: boolean;
699
+ language: string;
700
+ }
701
+
702
+ export interface ICartRetailer {
703
+ id: string;
704
+ name: string;
705
+ subtotal: number;
706
+ itemsQuantity: number;
707
+ fulfillments: Record<string, ICartFulfillment>;
708
+ }
709
+
710
+ export interface ICartFulfillment {
711
+ id: string;
712
+ canEngrave: boolean;
713
+ type: FulfillmentType;
714
+ expectation: string;
715
+ engravingExpectation: string;
716
+ itemIds: string[];
717
+ subtotal: number;
718
+ hasUnmetMinimumPurchaseAmount: boolean;
719
+ minimumPurchaseAmount: number;
720
+ }
721
+
722
+ export interface IAddressAddress {
723
+ one: string;
724
+ two: string;
725
+ city: string;
726
+ state: string;
727
+ zip: string;
728
+ country: string;
729
+ }
730
+
731
+ export interface IAddressCoordinates {
732
+ latitude: number;
733
+ longitude: number;
734
+ }
735
+ ```
736
+
737
+ **Example**
85
738
 
86
739
  ```js
87
740
  window.addEventListener('lce:actions.cart_updated', (event) => {
88
- const { cartId, itemsCount, subtotal } = event.detail.data;
741
+ const { data } = event.detail;
742
+ const delta = data.current.itemCount - data.previous.itemCount;
743
+ if (delta !== 0) console.log('Item count changed by', delta);
89
744
  });
90
745
  ```
91
746
 
92
- ## Checkout events
93
- - `lce:actions.checkout_loaded`
94
- Checkout state loaded.
95
- - `lce:actions.checkout_opened`
96
- Checkout drawer opened.
97
- - `lce:actions.checkout_closed`
98
- Checkout drawer closed.
99
- - `lce:actions.checkout_customer_information_updated`
100
- Customer info updated.
101
- - `lce:actions.checkout_billing_information_updated`
102
- Billing info updated.
103
- - `lce:actions.checkout_gift_information_updated`
104
- Gift info updated.
105
- - `lce:actions.checkout_is_gift_toggled`
106
- Gift mode toggled.
107
- - `lce:actions.checkout_billing_same_as_shipping_toggled`
108
- Billing same as shipping toggled.
109
- - `lce:actions.checkout_marketing_preferences_toggled`
110
- Marketing preferences toggled.
111
- - `lce:actions.checkout_submit_started`
112
- Checkout submit started.
113
- - `lce:actions.checkout_submit_completed`
114
- Checkout completed successfully.
115
- - `lce:actions.checkout_submit_failed`
116
- Checkout submission failed.
117
- - `lce:actions.checkout_promo_code_applied`
118
- Promo code applied in checkout.
119
- - `lce:actions.checkout_gift_card_applied`
120
- Gift card applied in checkout.
747
+ ### `lce:actions.cart_reset`
748
+
749
+ Cart cleared.
750
+
751
+ **Data shape (TypeScript)**
752
+
753
+ ```ts
754
+ export type CartResetEventData = boolean;
755
+ ```
756
+
757
+ **Example**
121
758
 
122
759
  ```js
123
- window.addEventListener('lce:actions.checkout_submit_completed', (event) => {
124
- const { orderId, total } = event.detail.data;
760
+ window.addEventListener('lce:actions.cart_reset', () => {
761
+ console.log('Cart reset');
125
762
  });
126
763
  ```
127
764
 
128
- ## Analytics example
765
+ ### `lce:actions.cart_failed`
766
+
767
+ Cart operation failed.
768
+
769
+ **Data shape (TypeScript)**
770
+
771
+ ```ts
772
+ export interface ICartFailedEventData {
773
+ cartId: string;
774
+ message: string;
775
+ }
776
+ ```
777
+
778
+ **Example**
779
+
780
+ ```js
781
+ window.addEventListener('lce:actions.cart_failed', (event) => {
782
+ const { data } = event.detail;
783
+ console.error('Cart error:', data.message);
784
+ });
785
+ ```
786
+
787
+ ### `lce:actions.cart_item_added`
788
+
789
+ Item added to cart.
790
+
791
+ **Data shape (TypeScript)**
792
+
793
+ ```ts
794
+ export interface ICartItemAddedEventData {
795
+ cartId: string;
796
+ itemId: string;
797
+ fulfillmentId: string;
798
+ partNumber: string;
799
+ quantity: number;
800
+ engravingLines?: string[];
801
+ }
802
+ ```
803
+
804
+ **Example**
805
+
806
+ ```js
807
+ window.addEventListener('lce:actions.cart_item_added', (event) => {
808
+ const { data } = event.detail;
809
+ console.log(`Added item ${data.itemId} (qty ${data.quantity})`);
810
+ });
811
+ ```
812
+
813
+ ### `lce:actions.cart_item_removed`
814
+
815
+ Item removed from cart.
816
+
817
+ **Data shape (TypeScript)**
818
+
819
+ ```ts
820
+ export interface ICartItemRemovedEventData {
821
+ cartId: string;
822
+ itemId: string;
823
+ }
824
+ ```
825
+
826
+ **Example**
827
+
828
+ ```js
829
+ window.addEventListener('lce:actions.cart_item_removed', (event) => {
830
+ const { data } = event.detail;
831
+ console.log('Removed item', data.itemId);
832
+ });
833
+ ```
834
+
835
+ ### `lce:actions.cart_item_quantity_increase`
836
+
837
+ Cart item quantity increased.
838
+
839
+ **Data shape (TypeScript)**
840
+
841
+ ```ts
842
+ export interface ICartItemQuantityChangedEventData {
843
+ cartId: string;
844
+ itemId: string;
845
+ quantity: number;
846
+ previousQuantity: number;
847
+ }
848
+ ```
849
+
850
+ **Example**
851
+
852
+ ```js
853
+ window.addEventListener('lce:actions.cart_item_quantity_increase', (event) => {
854
+ const { data } = event.detail;
855
+ console.log('Quantity increased to', data.quantity);
856
+ });
857
+ ```
858
+
859
+ ### `lce:actions.cart_item_quantity_decrease`
860
+
861
+ Cart item quantity decreased.
862
+
863
+ **Data shape (TypeScript)**
864
+
865
+ ```ts
866
+ export interface ICartItemQuantityChangedEventData {
867
+ cartId: string;
868
+ itemId: string;
869
+ quantity: number;
870
+ previousQuantity: number;
871
+ }
872
+ ```
873
+
874
+ **Example**
875
+
876
+ ```js
877
+ window.addEventListener('lce:actions.cart_item_quantity_decrease', (event) => {
878
+ const { data } = event.detail;
879
+ console.log('Quantity decreased to', data.quantity);
880
+ });
881
+ ```
882
+
883
+ ### `lce:actions.cart_item_engraving_updated`
884
+
885
+ Engraving text updated for a cart item.
886
+
887
+ **Data shape (TypeScript)**
888
+
889
+ ```ts
890
+ export interface ICartItemEngravingUpdatedEventData {
891
+ cartId: string;
892
+ itemId: string;
893
+ engravingLines: string[];
894
+ previousEngravingLines: string[];
895
+ }
896
+ ```
897
+
898
+ **Example**
899
+
900
+ ```js
901
+ window.addEventListener('lce:actions.cart_item_engraving_updated', (event) => {
902
+ const { data } = event.detail;
903
+ console.log('Updated engraving for', data.itemId);
904
+ });
905
+ ```
906
+
907
+ ### `lce:actions.cart_promo_code_applied`
908
+
909
+ Promo code applied to cart.
910
+
911
+ **Data shape (TypeScript)**
912
+
913
+ ```ts
914
+ export interface ICartPromoCodeEventData {
915
+ cartId: string;
916
+ discount?: number;
917
+ newSubtotal?: number;
918
+ }
919
+ ```
920
+
921
+ **Example**
922
+
923
+ ```js
924
+ window.addEventListener('lce:actions.cart_promo_code_applied', (event) => {
925
+ const { data } = event.detail;
926
+ console.log('Promo applied, discount:', data.discount);
927
+ });
928
+ ```
929
+
930
+ ### `lce:actions.cart_promo_code_removed`
931
+
932
+ Promo code removed from cart.
933
+
934
+ **Data shape (TypeScript)**
935
+
936
+ ```ts
937
+ export interface ICartPromoCodeEventData {
938
+ cartId: string;
939
+ discount?: number;
940
+ newSubtotal?: number;
941
+ }
942
+ ```
943
+
944
+ **Example**
945
+
946
+ ```js
947
+ window.addEventListener('lce:actions.cart_promo_code_removed', (event) => {
948
+ const { data } = event.detail;
949
+ console.log('Promo removed');
950
+ });
951
+ ```
952
+
953
+ ### `lce:actions.cart_promo_code_failed`
954
+
955
+ Promo code failed validation.
956
+
957
+ **Data shape (TypeScript)**
958
+
959
+ ```ts
960
+ export interface ICartPromoCodeFailedEventData {
961
+ cartId: string;
962
+ error: string;
963
+ }
964
+ ```
965
+
966
+ **Example**
967
+
968
+ ```js
969
+ window.addEventListener('lce:actions.cart_promo_code_failed', (event) => {
970
+ const { data } = event.detail;
971
+ console.error('Promo failed:', data.error);
972
+ });
973
+ ```
974
+
975
+ ### `lce:actions.cart_product_add_success`
976
+
977
+ Programmatic add-to-cart succeeded.
978
+
979
+ **Data shape (TypeScript)**
980
+
981
+ ```ts
982
+ export interface ICartProductAddEventData {
983
+ cartId: string;
984
+ itemsAdded: number;
985
+ identifiers: string[];
986
+ }
987
+ ```
988
+
989
+ **Example**
990
+
991
+ ```js
992
+ window.addEventListener('lce:actions.cart_product_add_success', (event) => {
993
+ const { data } = event.detail;
994
+ console.log(`Added ${data.itemsAdded} products`);
995
+ });
996
+ ```
997
+
998
+ ### `lce:actions.cart_product_add_failed`
999
+
1000
+ Programmatic add-to-cart failed.
1001
+
1002
+ **Data shape (TypeScript)**
1003
+
1004
+ ```ts
1005
+ export interface ICartProductAddFailedEventData {
1006
+ cartId: string;
1007
+ identifiers: string[];
1008
+ error: string;
1009
+ }
1010
+ ```
1011
+
1012
+ **Example**
1013
+
1014
+ ```js
1015
+ window.addEventListener('lce:actions.cart_product_add_failed', (event) => {
1016
+ const { data } = event.detail;
1017
+ console.error('Product add failed:', data.error);
1018
+ });
1019
+ ```
1020
+
1021
+ ## Checkout events
1022
+
1023
+ ### `lce:actions.checkout_loaded`
1024
+
1025
+ Checkout state loaded.
1026
+
1027
+ **Data shape (TypeScript)**
1028
+
1029
+ ```ts
1030
+ export interface IBaseCheckoutEventData {
1031
+ token: string;
1032
+ cartId: string;
1033
+ isGift: boolean;
1034
+ billingSameAsShipping: boolean;
1035
+ marketingPreferences: ICheckoutMarketingPreferences;
1036
+ hasPromoCode: boolean;
1037
+ hasGiftCards: boolean;
1038
+ amounts: ICheckoutAmounts;
1039
+ itemCount: number;
1040
+ items: Record<string, ICheckoutItem>;
1041
+ }
1042
+
1043
+ export interface ICheckoutMarketingPreferences {
1044
+ canEmail: boolean;
1045
+ canSms: boolean;
1046
+ }
1047
+
1048
+ export interface ICheckoutAmounts {
1049
+ subtotal: number;
1050
+ engraving: number;
1051
+ service: number;
1052
+ shipping: number;
1053
+ delivery: number;
1054
+ platform: number;
1055
+ discounts: number;
1056
+ giftCards: number;
1057
+ tax: number;
1058
+ tip: number;
1059
+ total: number;
1060
+ }
1061
+
1062
+ export interface ICheckoutItem {
1063
+ variantId: string;
1064
+ cartItemId: string;
1065
+ liquidId: string;
1066
+ retailerId: string;
1067
+ fulfillmentId: string;
1068
+ salsifyPid?: string;
1069
+ salsifyGrouping?: string;
1070
+ name: string;
1071
+ catPath: string;
1072
+ volume: string;
1073
+ uom: string;
1074
+ proof: string;
1075
+ abv: string;
1076
+ containerType: string;
1077
+ container: string;
1078
+ size: string;
1079
+ pack: boolean;
1080
+ packDesc: string;
1081
+ mainImage: string;
1082
+ brand: string;
1083
+ partNumber: string;
1084
+ upc: string;
1085
+ sku: string;
1086
+ price: number;
1087
+ unitPrice: number;
1088
+ quantity: number;
1089
+ tax: number;
1090
+ unitTax: number;
1091
+ bottleDeposits: number;
1092
+ attributes: ICheckoutItemAttributes;
1093
+ }
1094
+
1095
+ export interface ICheckoutItemAttributes {
1096
+ engraving: ICheckoutItemEngraving;
1097
+ presale: IProductPresale;
1098
+ }
1099
+
1100
+ export interface ICheckoutItemEngraving {
1101
+ isEngravable: boolean;
1102
+ hasEngraving: boolean;
1103
+ fee: number;
1104
+ maxCharsPerLine: number;
1105
+ maxLines: number;
1106
+ location: string;
1107
+ lines: string[];
1108
+ }
1109
+
1110
+ export interface IProductPresale {
1111
+ canPurchaseOn: string | null;
1112
+ estimatedShipBy: string | null;
1113
+ isActive: boolean;
1114
+ language: string;
1115
+ }
1116
+ ```
1117
+
1118
+ **Example**
1119
+
1120
+ ```js
1121
+ window.addEventListener('lce:actions.checkout_loaded', (event) => {
1122
+ const { data } = event.detail;
1123
+ console.log('Checkout loaded for cart', data.cartId);
1124
+ });
1125
+ ```
1126
+
1127
+ ### `lce:actions.checkout_opened`
1128
+
1129
+ Checkout drawer opened.
1130
+
1131
+ **Data shape (TypeScript)**
1132
+
1133
+ ```ts
1134
+ export type CheckoutOpenedEventData = boolean;
1135
+ ```
1136
+
1137
+ **Example**
1138
+
1139
+ ```js
1140
+ window.addEventListener('lce:actions.checkout_opened', () => {
1141
+ console.log('Checkout opened');
1142
+ });
1143
+ ```
1144
+
1145
+ ### `lce:actions.checkout_closed`
1146
+
1147
+ Checkout drawer closed.
1148
+
1149
+ **Data shape (TypeScript)**
1150
+
1151
+ ```ts
1152
+ export type CheckoutClosedEventData = boolean;
1153
+ ```
1154
+
1155
+ **Example**
1156
+
1157
+ ```js
1158
+ window.addEventListener('lce:actions.checkout_closed', () => {
1159
+ console.log('Checkout closed');
1160
+ });
1161
+ ```
1162
+
1163
+ ### `lce:actions.checkout_failed`
1164
+
1165
+ Checkout failed to load or operate.
1166
+
1167
+ **Data shape (TypeScript)**
1168
+
1169
+ ```ts
1170
+ export interface ICheckoutFailedEventData {
1171
+ message: string;
1172
+ }
1173
+ ```
1174
+
1175
+ **Example**
1176
+
1177
+ ```js
1178
+ window.addEventListener('lce:actions.checkout_failed', (event) => {
1179
+ const { data } = event.detail;
1180
+ console.error('Checkout error:', data.message);
1181
+ });
1182
+ ```
1183
+
1184
+ ### `lce:actions.checkout_customer_information_updated`
1185
+
1186
+ Customer info updated.
1187
+
1188
+ **Data shape (TypeScript)**
1189
+
1190
+ ```ts
1191
+ export interface ICheckoutCustomerInformationUpdatedEventData {
1192
+ cartId: string;
1193
+ }
1194
+ ```
1195
+
1196
+ **Example**
1197
+
1198
+ ```js
1199
+ window.addEventListener('lce:actions.checkout_customer_information_updated', (event) => {
1200
+ const { data } = event.detail;
1201
+ console.log('Customer info updated for cart', data.cartId);
1202
+ });
1203
+ ```
1204
+
1205
+ ### `lce:actions.checkout_billing_information_updated`
1206
+
1207
+ Billing info updated.
1208
+
1209
+ **Data shape (TypeScript)**
1210
+
1211
+ ```ts
1212
+ export interface ICheckoutBillingInformationUpdatedEventData {
1213
+ cartId: string;
1214
+ }
1215
+ ```
1216
+
1217
+ **Example**
1218
+
1219
+ ```js
1220
+ window.addEventListener('lce:actions.checkout_billing_information_updated', (event) => {
1221
+ const { data } = event.detail;
1222
+ console.log('Billing info updated for cart', data.cartId);
1223
+ });
1224
+ ```
1225
+
1226
+ ### `lce:actions.checkout_gift_information_updated`
1227
+
1228
+ Gift recipient info updated.
1229
+
1230
+ **Data shape (TypeScript)**
1231
+
1232
+ ```ts
1233
+ export interface ICheckoutGiftInformationUpdatedEventData {
1234
+ cartId: string;
1235
+ }
1236
+ ```
1237
+
1238
+ **Example**
1239
+
1240
+ ```js
1241
+ window.addEventListener('lce:actions.checkout_gift_information_updated', (event) => {
1242
+ const { data } = event.detail;
1243
+ console.log('Gift info updated for cart', data.cartId);
1244
+ });
1245
+ ```
1246
+
1247
+ ### `lce:actions.checkout_is_gift_toggled`
1248
+
1249
+ Gift mode toggled.
1250
+
1251
+ **Data shape (TypeScript)**
1252
+
1253
+ ```ts
1254
+ export interface ICheckoutToggleEventData {
1255
+ cartId: string;
1256
+ isActive: boolean;
1257
+ previousIsActive: boolean;
1258
+ }
1259
+ ```
1260
+
1261
+ **Example**
1262
+
1263
+ ```js
1264
+ window.addEventListener('lce:actions.checkout_is_gift_toggled', (event) => {
1265
+ const { data } = event.detail;
1266
+ console.log('Gift mode:', data.isActive);
1267
+ });
1268
+ ```
1269
+
1270
+ ### `lce:actions.checkout_billing_same_as_shipping_toggled`
1271
+
1272
+ Billing same-as-shipping toggled.
1273
+
1274
+ **Data shape (TypeScript)**
1275
+
1276
+ ```ts
1277
+ export interface ICheckoutToggleEventData {
1278
+ cartId: string;
1279
+ isActive: boolean;
1280
+ previousIsActive: boolean;
1281
+ }
1282
+ ```
1283
+
1284
+ **Example**
1285
+
1286
+ ```js
1287
+ window.addEventListener('lce:actions.checkout_billing_same_as_shipping_toggled', (event) => {
1288
+ const { data } = event.detail;
1289
+ console.log('Billing same as shipping:', data.isActive);
1290
+ });
1291
+ ```
1292
+
1293
+ ### `lce:actions.checkout_marketing_preferences_toggled`
1294
+
1295
+ Marketing preference toggled.
1296
+
1297
+ **Data shape (TypeScript)**
1298
+
1299
+ ```ts
1300
+ export interface ICheckoutMarketingPreferencesToggleEventData {
1301
+ cartId: string;
1302
+ fieldName: 'canEmail' | 'canSms';
1303
+ isActive: boolean;
1304
+ previousIsActive: boolean;
1305
+ }
1306
+ ```
1307
+
1308
+ **Example**
1309
+
1310
+ ```js
1311
+ window.addEventListener('lce:actions.checkout_marketing_preferences_toggled', (event) => {
1312
+ const { data } = event.detail;
1313
+ console.log(`Marketing ${data.fieldName}:`, data.isActive);
1314
+ });
1315
+ ```
1316
+
1317
+ ### `lce:actions.checkout_item_removed`
1318
+
1319
+ Item removed during checkout.
1320
+
1321
+ **Data shape (TypeScript)**
1322
+
1323
+ ```ts
1324
+ export interface ICheckoutItemRemovedEventData {
1325
+ cartId: string;
1326
+ cartItemId: string;
1327
+ }
1328
+ ```
1329
+
1330
+ **Example**
1331
+
1332
+ ```js
1333
+ window.addEventListener('lce:actions.checkout_item_removed', (event) => {
1334
+ const { data } = event.detail;
1335
+ console.log('Checkout item removed', data.cartItemId);
1336
+ });
1337
+ ```
1338
+
1339
+ ### `lce:actions.checkout_item_quantity_increase`
1340
+
1341
+ Checkout item quantity increased.
1342
+
1343
+ **Data shape (TypeScript)**
1344
+
1345
+ ```ts
1346
+ export interface ICheckoutItemQuantityChangedEventData {
1347
+ cartId: string;
1348
+ cartItemId: string;
1349
+ quantity: number;
1350
+ previousQuantity: number;
1351
+ }
1352
+ ```
1353
+
1354
+ **Example**
1355
+
1356
+ ```js
1357
+ window.addEventListener('lce:actions.checkout_item_quantity_increase', (event) => {
1358
+ const { data } = event.detail;
1359
+ console.log('Checkout quantity increased to', data.quantity);
1360
+ });
1361
+ ```
1362
+
1363
+ ### `lce:actions.checkout_item_quantity_decrease`
1364
+
1365
+ Checkout item quantity decreased.
1366
+
1367
+ **Data shape (TypeScript)**
1368
+
1369
+ ```ts
1370
+ export interface ICheckoutItemQuantityChangedEventData {
1371
+ cartId: string;
1372
+ cartItemId: string;
1373
+ quantity: number;
1374
+ previousQuantity: number;
1375
+ }
1376
+ ```
1377
+
1378
+ **Example**
1379
+
1380
+ ```js
1381
+ window.addEventListener('lce:actions.checkout_item_quantity_decrease', (event) => {
1382
+ const { data } = event.detail;
1383
+ console.log('Checkout quantity decreased to', data.quantity);
1384
+ });
1385
+ ```
1386
+
1387
+ ### `lce:actions.checkout_item_engraving_updated`
1388
+
1389
+ Engraving text updated for a checkout item.
1390
+
1391
+ **Data shape (TypeScript)**
1392
+
1393
+ ```ts
1394
+ export interface ICheckoutItemEngravingUpdatedEventData {
1395
+ cartId: string;
1396
+ cartItemId: string;
1397
+ engravingLines: string[];
1398
+ previousEngravingLines: string[];
1399
+ }
1400
+ ```
1401
+
1402
+ **Example**
1403
+
1404
+ ```js
1405
+ window.addEventListener('lce:actions.checkout_item_engraving_updated', (event) => {
1406
+ const { data } = event.detail;
1407
+ console.log('Checkout engraving updated for', data.cartItemId);
1408
+ });
1409
+ ```
1410
+
1411
+ ### `lce:actions.checkout_tip_updated`
1412
+
1413
+ Delivery tips updated.
1414
+
1415
+ **Data shape (TypeScript)**
1416
+
1417
+ ```ts
1418
+ export interface ICheckoutTipUpdatedEventData {
1419
+ cartId: string;
1420
+ deliveryTips: Array<{
1421
+ fulfillmentId: string;
1422
+ tip: number;
1423
+ }>;
1424
+ previousDeliveryTips: Array<{
1425
+ fulfillmentId: string;
1426
+ tip: number;
1427
+ }>;
1428
+ }
1429
+ ```
1430
+
1431
+ **Example**
1432
+
1433
+ ```js
1434
+ window.addEventListener('lce:actions.checkout_tip_updated', (event) => {
1435
+ const { data } = event.detail;
1436
+ console.log('Tips updated for cart', data.cartId);
1437
+ });
1438
+ ```
1439
+
1440
+ ### `lce:actions.checkout_submit_started`
1441
+
1442
+ Checkout submit started.
1443
+
1444
+ **Data shape (TypeScript)**
1445
+
1446
+ ```ts
1447
+ export interface ICheckoutSubmitStartedEventData {
1448
+ started: boolean;
1449
+ }
1450
+ ```
1451
+
1452
+ **Example**
1453
+
1454
+ ```js
1455
+ window.addEventListener('lce:actions.checkout_submit_started', (event) => {
1456
+ const { data } = event.detail;
1457
+ if (data.started) console.log('Checkout submit started');
1458
+ });
1459
+ ```
1460
+
1461
+ ### `lce:actions.checkout_submit_completed`
1462
+
1463
+ Checkout completed successfully.
1464
+
1465
+ **Data shape (TypeScript)**
1466
+
1467
+ ```ts
1468
+ export interface ICheckoutSubmitCompletedEventData {
1469
+ orderNumber: string;
1470
+ orderTotal: number;
1471
+ }
1472
+ ```
1473
+
1474
+ **Example**
1475
+
1476
+ ```js
1477
+ window.addEventListener('lce:actions.checkout_submit_completed', (event) => {
1478
+ const { data } = event.detail;
1479
+ console.log('Order completed:', data.orderNumber);
1480
+ });
1481
+ ```
1482
+
1483
+ ### `lce:actions.checkout_submit_failed`
1484
+
1485
+ Checkout submission failed.
1486
+
1487
+ **Data shape (TypeScript)**
1488
+
1489
+ ```ts
1490
+ export interface ICheckoutSubmitFailedEventData {
1491
+ message: string;
1492
+ }
1493
+ ```
1494
+
1495
+ **Example**
1496
+
1497
+ ```js
1498
+ window.addEventListener('lce:actions.checkout_submit_failed', (event) => {
1499
+ const { data } = event.detail;
1500
+ console.error('Checkout submit failed:', data.message);
1501
+ });
1502
+ ```
1503
+
1504
+ ### `lce:actions.checkout_promo_code_applied`
1505
+
1506
+ Promo code applied in checkout.
1507
+
1508
+ **Data shape (TypeScript)**
1509
+
1510
+ ```ts
1511
+ export interface ICheckoutPromoCodeEventData {
1512
+ cartId: string;
1513
+ discount?: number;
1514
+ newTotal?: number;
1515
+ }
1516
+ ```
1517
+
1518
+ **Example**
1519
+
1520
+ ```js
1521
+ window.addEventListener('lce:actions.checkout_promo_code_applied', (event) => {
1522
+ const { data } = event.detail;
1523
+ console.log('Checkout promo applied:', data.discount);
1524
+ });
1525
+ ```
1526
+
1527
+ ### `lce:actions.checkout_promo_code_removed`
1528
+
1529
+ Promo code removed in checkout.
1530
+
1531
+ **Data shape (TypeScript)**
1532
+
1533
+ ```ts
1534
+ export interface ICheckoutPromoCodeEventData {
1535
+ cartId: string;
1536
+ discount?: number;
1537
+ newTotal?: number;
1538
+ }
1539
+ ```
1540
+
1541
+ **Example**
1542
+
1543
+ ```js
1544
+ window.addEventListener('lce:actions.checkout_promo_code_removed', (event) => {
1545
+ const { data } = event.detail;
1546
+ console.log('Checkout promo removed');
1547
+ });
1548
+ ```
1549
+
1550
+ ### `lce:actions.checkout_promo_code_failed`
1551
+
1552
+ Promo code failed in checkout.
1553
+
1554
+ **Data shape (TypeScript)**
1555
+
1556
+ ```ts
1557
+ export interface ICheckoutPromoCodeFailedEventData {
1558
+ cartId: string;
1559
+ error: string;
1560
+ }
1561
+ ```
1562
+
1563
+ **Example**
1564
+
1565
+ ```js
1566
+ window.addEventListener('lce:actions.checkout_promo_code_failed', (event) => {
1567
+ const { data } = event.detail;
1568
+ console.error('Checkout promo failed:', data.error);
1569
+ });
1570
+ ```
1571
+
1572
+ ### `lce:actions.checkout_gift_card_applied`
1573
+
1574
+ Gift card applied in checkout.
1575
+
1576
+ **Data shape (TypeScript)**
1577
+
1578
+ ```ts
1579
+ export interface ICheckoutGiftCardEventData {
1580
+ cartId: string;
1581
+ newTotal?: number;
1582
+ }
1583
+ ```
1584
+
1585
+ **Example**
1586
+
1587
+ ```js
1588
+ window.addEventListener('lce:actions.checkout_gift_card_applied', (event) => {
1589
+ const { data } = event.detail;
1590
+ console.log('Gift card applied, new total:', data.newTotal);
1591
+ });
1592
+ ```
1593
+
1594
+ ### `lce:actions.checkout_gift_card_removed`
1595
+
1596
+ Gift card removed in checkout.
1597
+
1598
+ **Data shape (TypeScript)**
1599
+
1600
+ ```ts
1601
+ export interface ICheckoutGiftCardEventData {
1602
+ cartId: string;
1603
+ newTotal?: number;
1604
+ }
1605
+ ```
1606
+
1607
+ **Example**
1608
+
1609
+ ```js
1610
+ window.addEventListener('lce:actions.checkout_gift_card_removed', (event) => {
1611
+ const { data } = event.detail;
1612
+ console.log('Gift card removed');
1613
+ });
1614
+ ```
1615
+
1616
+ ### `lce:actions.checkout_gift_card_failed`
1617
+
1618
+ Gift card failed in checkout.
1619
+
1620
+ **Data shape (TypeScript)**
1621
+
1622
+ ```ts
1623
+ export interface ICheckoutGiftCardFailedEventData {
1624
+ cartId: string;
1625
+ error: string;
1626
+ }
1627
+ ```
1628
+
1629
+ **Example**
1630
+
1631
+ ```js
1632
+ window.addEventListener('lce:actions.checkout_gift_card_failed', (event) => {
1633
+ const { data } = event.detail;
1634
+ console.error('Gift card failed:', data.error);
1635
+ });
1636
+ ```
1637
+
1638
+ ### `lce:actions.checkout_product_add_success`
1639
+
1640
+ Programmatic add-to-checkout succeeded.
1641
+
1642
+ **Data shape (TypeScript)**
1643
+
1644
+ ```ts
1645
+ export interface ICheckoutProductAddEventData {
1646
+ cartId: string;
1647
+ itemsAdded: number;
1648
+ identifiers: string[];
1649
+ isPresale?: boolean;
1650
+ }
1651
+ ```
1652
+
1653
+ **Example**
1654
+
1655
+ ```js
1656
+ window.addEventListener('lce:actions.checkout_product_add_success', (event) => {
1657
+ const { data } = event.detail;
1658
+ console.log(`Checkout added ${data.itemsAdded} products`);
1659
+ });
1660
+ ```
1661
+
1662
+ ### `lce:actions.checkout_product_add_failed`
1663
+
1664
+ Programmatic add-to-checkout failed.
1665
+
1666
+ **Data shape (TypeScript)**
1667
+
1668
+ ```ts
1669
+ export interface ICheckoutProductAddFailedEventData {
1670
+ cartId: string;
1671
+ identifiers: string[];
1672
+ error: string;
1673
+ isPresale?: boolean;
1674
+ }
1675
+ ```
1676
+
1677
+ **Example**
1678
+
1679
+ ```js
1680
+ window.addEventListener('lce:actions.checkout_product_add_failed', (event) => {
1681
+ const { data } = event.detail;
1682
+ console.error('Checkout product add failed:', data.error);
1683
+ });
1684
+ ```
1685
+
1686
+ ## Form events
1687
+
1688
+ ### `lce:forms.customer`
1689
+
1690
+ Fires when a customer form field changes in checkout.
1691
+
1692
+ **Data shape (TypeScript)**
1693
+
1694
+ ```ts
1695
+ export interface IFormEventData {
1696
+ fieldName: string;
1697
+ fieldValue?: string;
1698
+ }
1699
+ ```
1700
+
1701
+ **Example**
1702
+
1703
+ ```js
1704
+ window.addEventListener('lce:forms.customer', (event) => {
1705
+ const { data } = event.detail;
1706
+ console.log('Customer field changed:', data.fieldName);
1707
+ });
1708
+ ```
1709
+
1710
+ ### `lce:forms.billing`
1711
+
1712
+ Fires when a billing form field changes in checkout.
1713
+
1714
+ **Data shape (TypeScript)**
1715
+
1716
+ ```ts
1717
+ export interface IFormEventData {
1718
+ fieldName: string;
1719
+ fieldValue?: string;
1720
+ }
1721
+ ```
1722
+
1723
+ **Example**
1724
+
1725
+ ```js
1726
+ window.addEventListener('lce:forms.billing', (event) => {
1727
+ const { data } = event.detail;
1728
+ console.log('Billing field changed:', data.fieldName);
1729
+ });
1730
+ ```
1731
+
1732
+ ### `lce:forms.gift`
1733
+
1734
+ Fires when a gift form field changes in checkout.
1735
+
1736
+ **Data shape (TypeScript)**
1737
+
1738
+ ```ts
1739
+ export interface IFormEventData {
1740
+ fieldName: string;
1741
+ fieldValue?: string;
1742
+ }
1743
+ ```
1744
+
1745
+ **Example**
1746
+
1747
+ ```js
1748
+ window.addEventListener('lce:forms.gift', (event) => {
1749
+ const { data } = event.detail;
1750
+ console.log('Gift field changed:', data.fieldName);
1751
+ });
1752
+ ```
1753
+
1754
+ ## Analytics example
1755
+
129
1756
  ```js
130
1757
  window.addEventListener('lce:actions.checkout_submit_completed', (event) => {
1758
+ const { data } = event.detail;
131
1759
  gtag('event', 'purchase', {
132
- transaction_id: event.detail.data.orderId,
133
- value: event.detail.data.total / 100,
1760
+ transaction_id: data.orderNumber,
1761
+ value: data.orderTotal / 100,
134
1762
  currency: 'USD'
135
1763
  });
136
1764
  });