@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.
- package/dist/contexts/CartContext.d.ts +2 -0
- package/dist/contexts/CartContext.d.ts.map +1 -1
- package/dist/index134.mjs +2 -2
- package/dist/index135.mjs +1 -1
- package/dist/index136.mjs +6 -6
- package/dist/index137.mjs +2 -2
- package/dist/index138.mjs +2 -2
- package/dist/index140.mjs +2 -2
- package/dist/index141.mjs +2 -2
- package/dist/index142.mjs +1 -1
- package/dist/index144.mjs +8 -8
- package/dist/index145.mjs +8 -8
- package/dist/index150.mjs +1 -1
- package/dist/index151.mjs +1 -1
- package/dist/index152.mjs +1 -1
- package/dist/index153.mjs +1 -1
- package/dist/index154.mjs +1 -1
- package/dist/index156.mjs +1 -1
- package/dist/index157.mjs +1 -1
- package/dist/index159.mjs +2 -2
- package/dist/index160.mjs +1 -1
- package/dist/index165.mjs +2 -2
- package/dist/index167.mjs +1 -1
- package/dist/index169.mjs +2 -2
- package/dist/index170.mjs +5 -5
- package/dist/index173.mjs +1 -1
- package/dist/index176.mjs +1 -1
- package/dist/index179.mjs +1 -1
- package/dist/index180.mjs +1 -1
- package/dist/index184.mjs +1 -1
- package/dist/index186.mjs +1 -1
- package/dist/index190.mjs +1 -1
- package/dist/index192.mjs +1 -1
- package/dist/index201.mjs +2 -2
- package/dist/index203.mjs +1 -1
- package/dist/index204.mjs +1 -1
- package/dist/index205.mjs +2 -31
- package/dist/index206.mjs +2 -11
- package/dist/index207.mjs +2 -4
- package/dist/index208.mjs +2 -4
- package/dist/index209.mjs +2 -13
- package/dist/index210.mjs +2 -7
- package/dist/index211.mjs +2 -12
- package/dist/index212.mjs +2 -5
- package/dist/index213.mjs +108 -33
- package/dist/index214.mjs +2 -31
- package/dist/index215.mjs +2 -28
- package/dist/index216.mjs +34 -58
- package/dist/index217.mjs +2 -2
- package/dist/index218.mjs +244 -2
- package/dist/index219.mjs +2 -2
- package/dist/index220.mjs +33 -2
- package/dist/index221.mjs +65 -2
- package/dist/index222.mjs +25 -2
- package/dist/index225.mjs +2 -108
- package/dist/index226.mjs +2 -2
- package/dist/index227.mjs +2 -2
- package/dist/index228.mjs +2 -2
- package/dist/index229.mjs +2 -37
- package/dist/index230.mjs +2 -2
- package/dist/index231.mjs +2 -244
- package/dist/index232.mjs +2 -2
- package/dist/index233.mjs +4 -33
- package/dist/index234.mjs +2 -65
- package/dist/index235.mjs +2 -25
- package/dist/index236.mjs +31 -2
- package/dist/index237.mjs +11 -2
- package/dist/index238.mjs +4 -2
- package/dist/index239.mjs +4 -2
- package/dist/index240.mjs +13 -2
- package/dist/index241.mjs +7 -2
- package/dist/index242.mjs +12 -2
- package/dist/index243.mjs +5 -2
- package/dist/index244.mjs +33 -2
- package/dist/index245.mjs +31 -4
- package/dist/index246.mjs +28 -2
- package/dist/index247.mjs +61 -2
- package/dist/index25.mjs +48 -48
- package/dist/index252.mjs +2 -2
- package/dist/index253.mjs +2 -2
- package/dist/index254.mjs +2 -2
- package/dist/index255.mjs +91 -2
- package/dist/index256.mjs +2 -91
- package/dist/index257.mjs +1 -2
- package/dist/index258.mjs +3 -2
- package/dist/index259.mjs +2 -2
- package/dist/index260.mjs +2 -17
- package/dist/index261.mjs +15 -11
- package/dist/index262.mjs +13 -6
- package/dist/index263.mjs +6 -30
- package/dist/index264.mjs +30 -2
- package/dist/index3.mjs +133 -102
- package/dist/index32.mjs +26 -26
- package/dist/index37.mjs +2 -2
- package/dist/index38.mjs +2 -2
- package/dist/index4.mjs +50 -49
- package/dist/index42.mjs +1 -1
- package/dist/index47.mjs +17 -17
- package/dist/index48.mjs +2 -2
- package/dist/index60.mjs +21 -20
- package/dist/index61.mjs +2 -24
- package/dist/index62.mjs +19 -149
- package/dist/index63.mjs +153 -2
- package/dist/index66.mjs +2 -2
- package/dist/index73.mjs +1 -1
- package/dist/index75.mjs +2 -235
- package/dist/index76.mjs +233 -4
- package/dist/index77.mjs +5 -133
- package/dist/index78.mjs +129 -63
- package/dist/index79.mjs +67 -86
- package/dist/index80.mjs +85 -27
- package/dist/index81.mjs +28 -8
- package/dist/index82.mjs +8 -74
- package/dist/index83.mjs +74 -3
- package/dist/index84.mjs +4 -2
- package/dist/index85.mjs +2 -83
- package/dist/index86.mjs +81 -52
- package/dist/index87.mjs +53 -5
- package/dist/index88.mjs +5 -4
- package/dist/index89.mjs +4 -178
- package/dist/index90.mjs +174 -48
- package/dist/index91.mjs +51 -67
- package/dist/index92.mjs +69 -34
- package/dist/index93.mjs +31 -40
- package/dist/index94.mjs +43 -2
- package/dist/providers/MetaPixelProvider.d.ts +10 -5
- package/dist/providers/MetaPixelProvider.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/contexts/CartContext.tsx +69 -6
- 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
|
-
//
|
|
251
|
-
|
|
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
|
|
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
|
-
|
|
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,
|
|
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 = {
|