@instockng/storefront-ui 1.0.21 → 1.0.22

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 (130) hide show
  1. package/dist/contexts/CartContext.d.ts +2 -0
  2. package/dist/contexts/CartContext.d.ts.map +1 -1
  3. package/dist/index134.mjs +2 -2
  4. package/dist/index135.mjs +1 -1
  5. package/dist/index136.mjs +6 -6
  6. package/dist/index137.mjs +2 -2
  7. package/dist/index138.mjs +2 -2
  8. package/dist/index140.mjs +2 -2
  9. package/dist/index141.mjs +2 -2
  10. package/dist/index142.mjs +1 -1
  11. package/dist/index144.mjs +8 -8
  12. package/dist/index145.mjs +8 -8
  13. package/dist/index150.mjs +1 -1
  14. package/dist/index151.mjs +1 -1
  15. package/dist/index152.mjs +1 -1
  16. package/dist/index153.mjs +1 -1
  17. package/dist/index154.mjs +1 -1
  18. package/dist/index156.mjs +1 -1
  19. package/dist/index157.mjs +1 -1
  20. package/dist/index159.mjs +2 -2
  21. package/dist/index160.mjs +1 -1
  22. package/dist/index165.mjs +2 -2
  23. package/dist/index167.mjs +1 -1
  24. package/dist/index169.mjs +2 -2
  25. package/dist/index170.mjs +5 -5
  26. package/dist/index173.mjs +1 -1
  27. package/dist/index176.mjs +1 -1
  28. package/dist/index179.mjs +1 -1
  29. package/dist/index180.mjs +1 -1
  30. package/dist/index184.mjs +1 -1
  31. package/dist/index186.mjs +1 -1
  32. package/dist/index190.mjs +1 -1
  33. package/dist/index192.mjs +1 -1
  34. package/dist/index201.mjs +2 -2
  35. package/dist/index203.mjs +1 -1
  36. package/dist/index204.mjs +1 -1
  37. package/dist/index205.mjs +2 -31
  38. package/dist/index206.mjs +2 -11
  39. package/dist/index207.mjs +2 -4
  40. package/dist/index208.mjs +2 -4
  41. package/dist/index209.mjs +2 -13
  42. package/dist/index210.mjs +2 -7
  43. package/dist/index211.mjs +2 -12
  44. package/dist/index212.mjs +2 -5
  45. package/dist/index213.mjs +108 -33
  46. package/dist/index214.mjs +2 -31
  47. package/dist/index215.mjs +2 -28
  48. package/dist/index216.mjs +34 -58
  49. package/dist/index217.mjs +2 -2
  50. package/dist/index218.mjs +244 -2
  51. package/dist/index219.mjs +2 -2
  52. package/dist/index220.mjs +33 -2
  53. package/dist/index221.mjs +65 -2
  54. package/dist/index222.mjs +25 -2
  55. package/dist/index225.mjs +2 -108
  56. package/dist/index226.mjs +2 -2
  57. package/dist/index227.mjs +2 -2
  58. package/dist/index228.mjs +2 -2
  59. package/dist/index229.mjs +2 -37
  60. package/dist/index230.mjs +2 -2
  61. package/dist/index231.mjs +2 -244
  62. package/dist/index232.mjs +2 -2
  63. package/dist/index233.mjs +4 -33
  64. package/dist/index234.mjs +2 -65
  65. package/dist/index235.mjs +2 -25
  66. package/dist/index236.mjs +31 -2
  67. package/dist/index237.mjs +11 -2
  68. package/dist/index238.mjs +4 -2
  69. package/dist/index239.mjs +4 -2
  70. package/dist/index240.mjs +13 -2
  71. package/dist/index241.mjs +7 -2
  72. package/dist/index242.mjs +12 -2
  73. package/dist/index243.mjs +5 -2
  74. package/dist/index244.mjs +33 -2
  75. package/dist/index245.mjs +31 -4
  76. package/dist/index246.mjs +28 -2
  77. package/dist/index247.mjs +61 -2
  78. package/dist/index25.mjs +48 -48
  79. package/dist/index252.mjs +2 -2
  80. package/dist/index253.mjs +2 -2
  81. package/dist/index254.mjs +2 -2
  82. package/dist/index255.mjs +91 -2
  83. package/dist/index256.mjs +2 -91
  84. package/dist/index257.mjs +1 -2
  85. package/dist/index258.mjs +3 -2
  86. package/dist/index259.mjs +2 -2
  87. package/dist/index260.mjs +2 -17
  88. package/dist/index261.mjs +15 -11
  89. package/dist/index262.mjs +13 -6
  90. package/dist/index263.mjs +6 -30
  91. package/dist/index264.mjs +30 -2
  92. package/dist/index3.mjs +133 -102
  93. package/dist/index32.mjs +26 -26
  94. package/dist/index37.mjs +2 -2
  95. package/dist/index38.mjs +2 -2
  96. package/dist/index4.mjs +50 -49
  97. package/dist/index42.mjs +1 -1
  98. package/dist/index47.mjs +17 -17
  99. package/dist/index48.mjs +2 -2
  100. package/dist/index60.mjs +21 -20
  101. package/dist/index61.mjs +2 -24
  102. package/dist/index62.mjs +19 -149
  103. package/dist/index63.mjs +153 -2
  104. package/dist/index66.mjs +2 -2
  105. package/dist/index73.mjs +1 -1
  106. package/dist/index75.mjs +2 -235
  107. package/dist/index76.mjs +233 -4
  108. package/dist/index77.mjs +5 -133
  109. package/dist/index78.mjs +129 -63
  110. package/dist/index79.mjs +67 -86
  111. package/dist/index80.mjs +85 -27
  112. package/dist/index81.mjs +28 -8
  113. package/dist/index82.mjs +8 -74
  114. package/dist/index83.mjs +74 -3
  115. package/dist/index84.mjs +4 -2
  116. package/dist/index85.mjs +2 -83
  117. package/dist/index86.mjs +81 -52
  118. package/dist/index87.mjs +53 -5
  119. package/dist/index88.mjs +5 -4
  120. package/dist/index89.mjs +4 -178
  121. package/dist/index90.mjs +174 -48
  122. package/dist/index91.mjs +51 -67
  123. package/dist/index92.mjs +69 -34
  124. package/dist/index93.mjs +31 -40
  125. package/dist/index94.mjs +43 -2
  126. package/dist/providers/MetaPixelProvider.d.ts +10 -5
  127. package/dist/providers/MetaPixelProvider.d.ts.map +1 -1
  128. package/package.json +4 -4
  129. package/src/contexts/CartContext.tsx +69 -6
  130. package/src/providers/MetaPixelProvider.tsx +24 -16
@@ -49,6 +49,8 @@ interface CartContextValue {
49
49
  applyDiscount: (code: string) => Promise<void>;
50
50
  /** Remove discount code */
51
51
  removeDiscount: () => Promise<void>;
52
+ /** Track InitiateCheckout event (call when user starts checkout flow) */
53
+ trackCheckoutInitiated: () => void;
52
54
  /** Clear cart (removes from localStorage) */
53
55
  clearCart: () => void;
54
56
  /** Clear cart and create a new one immediately */
@@ -92,7 +94,26 @@ export function CartProvider({ children, brandSlug, initialCartId, shoppingCartP
92
94
  const isHandlingErrorRef = useRef(false);
93
95
 
94
96
  // Get Meta Pixel tracking methods
95
- const { trackAddToCart, trackPurchase } = useMetaPixel();
97
+ const { trackAddToCart, trackInitiateCheckout, trackPurchase } = useMetaPixel();
98
+
99
+ /**
100
+ * Extract fbc (Facebook Click ID) and fbp (Facebook Browser ID) cookies for attribution
101
+ */
102
+ const getFbCookies = useCallback(() => {
103
+ if (typeof document === 'undefined') return { fbc: undefined, fbp: undefined };
104
+
105
+ const getCookie = (name: string) => {
106
+ const value = `; ${document.cookie}`;
107
+ const parts = value.split(`; ${name}=`);
108
+ if (parts.length === 2) return parts.pop()?.split(';').shift();
109
+ return undefined;
110
+ };
111
+
112
+ return {
113
+ fbc: getCookie('_fbc'),
114
+ fbp: getCookie('_fbp'),
115
+ };
116
+ }, []);
96
117
 
97
118
  // Set mounted flag on client
98
119
  useEffect(() => {
@@ -226,11 +247,15 @@ export function CartProvider({ children, brandSlug, initialCartId, shoppingCartP
226
247
  item_price: Number(item.priceAtPurchase),
227
248
  })) || [];
228
249
 
250
+ // Generate event ID matching backend format: order_{orderId}
251
+ const eventID = `order_${order.id}`;
252
+
229
253
  trackPurchase(
230
254
  Number(order.totalPrice),
231
255
  'NGN',
232
256
  order.id,
233
- items
257
+ items,
258
+ eventID
234
259
  );
235
260
  },
236
261
  });
@@ -245,13 +270,34 @@ export function CartProvider({ children, brandSlug, initialCartId, shoppingCartP
245
270
  const addItem = useCallback(
246
271
  async (productSlug: string, productName: string, price: number, sku: string, quantity: number) => {
247
272
  if (!cartId) throw new Error('No cart ID');
248
- await addItemMutation.mutateAsync({ sku, quantity });
249
273
 
250
- // Track AddToCart event with Meta Pixel
251
- trackAddToCart(productSlug, productName, price, quantity);
274
+ // Get Facebook cookies for attribution
275
+ const { fbc, fbp } = getFbCookies();
276
+
277
+ // Add item to cart via API
278
+ const updatedCart = await addItemMutation.mutateAsync({ sku, quantity, fbc, fbp });
279
+
280
+ // Skip tracking if error response
281
+ if ('error' in updatedCart) return;
282
+
283
+ // Find the newly added item (last item with matching SKU)
284
+ const addedItem = updatedCart.items?.findLast(
285
+ (item) => item.variant?.sku === sku
286
+ );
287
+
288
+ if (addedItem) {
289
+ // Generate event ID matching backend format: cart_{cartId}_item_{itemId}
290
+ const eventID = `cart_${cartId}_item_${addedItem.id}`;
291
+
292
+ // Track AddToCart event with Meta Pixel and matching event ID
293
+ trackAddToCart(productSlug, productName, price, quantity, eventID);
294
+ } else {
295
+ // Fallback without event ID if item not found
296
+ trackAddToCart(productSlug, productName, price, quantity);
297
+ }
252
298
  },
253
299
  // eslint-disable-next-line react-hooks/exhaustive-deps
254
- [cartId, trackAddToCart]
300
+ [cartId, trackAddToCart, getFbCookies]
255
301
  );
256
302
 
257
303
  const updateItem = useCallback(
@@ -310,6 +356,22 @@ export function CartProvider({ children, brandSlug, initialCartId, shoppingCartP
310
356
  setIsOpen(false);
311
357
  }, []);
312
358
 
359
+ const trackCheckoutInitiated = useCallback(() => {
360
+ if (!cart || !cartId) return;
361
+
362
+ // Get cart total from pricing
363
+ const cartTotal = Number(cart.pricing?.total || 0);
364
+
365
+ // Calculate item count
366
+ const itemCount = cart.items?.reduce((sum, item) => sum + item.quantity, 0) || 0;
367
+
368
+ // Generate event ID matching backend format: cart_{cartId}_checkout
369
+ const eventID = `cart_${cartId}_checkout`;
370
+
371
+ // Track InitiateCheckout event with Meta Pixel
372
+ trackInitiateCheckout(cartTotal, itemCount, eventID);
373
+ }, [cart, cartId, trackInitiateCheckout]);
374
+
313
375
  const value: CartContextValue = {
314
376
  cart: cart || null,
315
377
  cartId,
@@ -322,6 +384,7 @@ export function CartProvider({ children, brandSlug, initialCartId, shoppingCartP
322
384
  removeItem,
323
385
  applyDiscount,
324
386
  removeDiscount,
387
+ trackCheckoutInitiated,
325
388
  clearCart,
326
389
  clearAndCreateNewCart,
327
390
  refetch,
@@ -18,7 +18,7 @@ interface MetaPixelContextValue {
18
18
  /**
19
19
  * Track a custom event
20
20
  */
21
- track: (event: string, data?: Record<string, unknown>) => void;
21
+ track: (event: string, data?: Record<string, unknown>, eventID?: string) => void;
22
22
 
23
23
  /**
24
24
  * Track a page view
@@ -28,7 +28,7 @@ interface MetaPixelContextValue {
28
28
  /**
29
29
  * Track product view
30
30
  */
31
- trackProductView: (productId: string, productName: string, price: number) => void;
31
+ trackProductView: (productId: string, productName: string, price: number, eventID?: string) => void;
32
32
 
33
33
  /**
34
34
  * Track add to cart event
@@ -36,13 +36,17 @@ interface MetaPixelContextValue {
36
36
  * @param productName - Product name
37
37
  * @param price - Unit price (not total)
38
38
  * @param quantity - Quantity added
39
+ * @param eventID - Optional event ID for deduplication with CAPI
39
40
  */
40
- trackAddToCart: (productId: string, productName: string, price: number, quantity: number) => void;
41
+ trackAddToCart: (productId: string, productName: string, price: number, quantity: number, eventID?: string) => void;
41
42
 
42
43
  /**
43
44
  * Track begin checkout event
45
+ * @param cartTotal - Total cart value
46
+ * @param itemCount - Number of items
47
+ * @param eventID - Optional event ID for deduplication with CAPI
44
48
  */
45
- trackInitiateCheckout: (cartTotal: number, itemCount: number) => void;
49
+ trackInitiateCheckout: (cartTotal: number, itemCount: number, eventID?: string) => void;
46
50
 
47
51
  /**
48
52
  * Track purchase event
@@ -50,8 +54,9 @@ interface MetaPixelContextValue {
50
54
  * @param currency - Currency code (e.g., 'NGN', 'USD')
51
55
  * @param orderId - Order ID or order number
52
56
  * @param items - Array of purchased items with SKU, quantity, and price
57
+ * @param eventID - Optional event ID for deduplication with CAPI
53
58
  */
54
- trackPurchase: (orderTotal: number, currency: string, orderId: string, items: PurchaseItem[]) => void;
59
+ trackPurchase: (orderTotal: number, currency: string, orderId: string, items: PurchaseItem[], eventID?: string) => void;
55
60
 
56
61
  /**
57
62
  * Whether the pixel is initialized
@@ -126,7 +131,7 @@ export function MetaPixelProvider({ children, pixelId, debug }: MetaPixelProvide
126
131
  });
127
132
  }, [pixelId, shouldDebug]);
128
133
 
129
- const track = (event: string, data?: Record<string, unknown>) => {
134
+ const track = (event: string, data?: Record<string, unknown>, eventID?: string) => {
130
135
  if (!isInitialized || !reactPixel) {
131
136
  if (shouldDebug) {
132
137
  console.log('[Meta Pixel] Track (not initialized):', event, data);
@@ -134,10 +139,13 @@ export function MetaPixelProvider({ children, pixelId, debug }: MetaPixelProvide
134
139
  return;
135
140
  }
136
141
 
137
- reactPixel.track(event, data);
142
+ // Include eventID for deduplication with CAPI
143
+ const eventData = eventID ? { ...data, eventID } : data;
144
+
145
+ reactPixel.track(event, eventData);
138
146
 
139
147
  if (shouldDebug) {
140
- console.log('[Meta Pixel] Track:', event, data);
148
+ console.log('[Meta Pixel] Track:', event, eventData, eventID ? `(ID: ${eventID})` : '');
141
149
  }
142
150
  };
143
151
 
@@ -156,17 +164,17 @@ export function MetaPixelProvider({ children, pixelId, debug }: MetaPixelProvide
156
164
  }
157
165
  };
158
166
 
159
- const trackProductView = (productId: string, productName: string, price: number) => {
167
+ const trackProductView = (productId: string, productName: string, price: number, eventID?: string) => {
160
168
  track('ViewContent', {
161
169
  content_ids: [productId],
162
170
  content_name: productName,
163
171
  content_type: 'product',
164
172
  value: price,
165
173
  currency: 'NGN',
166
- });
174
+ }, eventID);
167
175
  };
168
176
 
169
- const trackAddToCart = (productId: string, productName: string, price: number, quantity: number) => {
177
+ const trackAddToCart = (productId: string, productName: string, price: number, quantity: number, eventID?: string) => {
170
178
  track('AddToCart', {
171
179
  content_ids: [productId],
172
180
  content_name: productName,
@@ -174,18 +182,18 @@ export function MetaPixelProvider({ children, pixelId, debug }: MetaPixelProvide
174
182
  value: price,
175
183
  currency: 'NGN',
176
184
  num_items: quantity,
177
- });
185
+ }, eventID);
178
186
  };
179
187
 
180
- const trackInitiateCheckout = (cartTotal: number, itemCount: number) => {
188
+ const trackInitiateCheckout = (cartTotal: number, itemCount: number, eventID?: string) => {
181
189
  track('InitiateCheckout', {
182
190
  value: cartTotal,
183
191
  currency: 'NGN',
184
192
  num_items: itemCount,
185
- });
193
+ }, eventID);
186
194
  };
187
195
 
188
- const trackPurchase = (orderTotal: number, currency: string, orderId: string, items: PurchaseItem[]) => {
196
+ const trackPurchase = (orderTotal: number, currency: string, orderId: string, items: PurchaseItem[], eventID?: string) => {
189
197
  track('Purchase', {
190
198
  value: orderTotal,
191
199
  currency,
@@ -196,7 +204,7 @@ export function MetaPixelProvider({ children, pixelId, debug }: MetaPixelProvide
196
204
  item_price: item.item_price,
197
205
  })),
198
206
  order_id: orderId,
199
- });
207
+ }, eventID);
200
208
  };
201
209
 
202
210
  const value: MetaPixelContextValue = {