@instockng/storefront-ui 1.0.31 → 1.0.33
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/components/Checkout.d.ts.map +1 -1
- package/dist/contexts/CartContext.d.ts.map +1 -1
- package/dist/hooks/usePaystackPayment.d.ts +2 -1
- package/dist/hooks/usePaystackPayment.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +99 -96
- package/dist/index10.mjs +85 -162
- package/dist/index100.mjs +210 -17
- package/dist/index101.mjs +174 -17
- package/dist/index102.mjs +14 -25
- package/dist/index103.mjs +17 -150
- package/dist/index104.mjs +26 -13
- package/dist/index105.mjs +149 -24
- package/dist/index106.mjs +13 -77
- package/dist/index107.mjs +20 -27
- package/dist/index108.mjs +76 -137
- package/dist/index109.mjs +33 -50
- package/dist/index11.mjs +171 -94
- package/dist/index110.mjs +141 -19
- package/dist/index111.mjs +50 -22
- package/dist/index112.mjs +14 -14
- package/dist/index113.mjs +20 -18
- package/dist/index114.mjs +16 -14
- package/dist/index115.mjs +17 -14
- package/dist/index116.mjs +12 -12
- package/dist/index117.mjs +15 -58
- package/dist/index118.mjs +14 -11
- package/dist/index119.mjs +56 -30
- package/dist/index12.mjs +82 -658
- package/dist/index120.mjs +9 -15
- package/dist/index121.mjs +31 -26
- package/dist/index122.mjs +13 -16
- package/dist/index123.mjs +26 -11
- package/dist/index124.mjs +18 -12
- package/dist/index125.mjs +12 -40
- package/dist/index126.mjs +14 -16
- package/dist/index127.mjs +42 -263
- package/dist/index128.mjs +15 -62
- package/dist/index129.mjs +267 -7
- package/dist/index13.mjs +668 -53
- package/dist/index130.mjs +70 -2
- package/dist/index131.mjs +8 -2
- package/dist/index132.mjs +2 -33
- package/dist/index133.mjs +2 -2
- package/dist/index134.mjs +32 -20
- package/dist/index135.mjs +2 -56
- package/dist/index136.mjs +18 -26
- package/dist/index137.mjs +55 -6
- package/dist/index138.mjs +28 -51
- package/dist/index139.mjs +7 -6
- package/dist/index14.mjs +58 -60
- package/dist/index140.mjs +51 -11
- package/dist/index141.mjs +5 -6
- package/dist/index142.mjs +12 -28
- package/dist/index143.mjs +7 -2
- package/dist/index144.mjs +27 -69
- package/dist/index145.mjs +2 -167
- package/dist/index146.mjs +70 -2
- package/dist/index147.mjs +167 -2
- package/dist/index149.mjs +2 -2
- package/dist/index15.mjs +60 -22
- package/dist/index150.mjs +2 -18
- package/dist/index151.mjs +11 -25
- package/dist/index152.mjs +26 -32
- package/dist/index153.mjs +32 -12
- package/dist/index154.mjs +9 -9
- package/dist/index155.mjs +18 -2
- package/dist/index156.mjs +2 -20
- package/dist/index157.mjs +13 -39
- package/dist/index158.mjs +46 -2
- package/dist/index159.mjs +2 -30
- package/dist/index16.mjs +22 -113
- package/dist/index160.mjs +24 -12
- package/dist/index161.mjs +18 -2
- package/dist/index162.mjs +2 -2
- package/dist/index163.mjs +2 -2
- package/dist/index164.mjs +2 -2
- package/dist/index165.mjs +2 -72
- package/dist/index166.mjs +72 -2
- package/dist/index167.mjs +2 -53
- package/dist/index168.mjs +53 -2
- package/dist/index169.mjs +2 -36
- package/dist/index17.mjs +111 -38
- package/dist/index170.mjs +30 -146
- package/dist/index171.mjs +152 -2
- package/dist/index172.mjs +2 -2
- package/dist/index173.mjs +2 -19
- package/dist/index174.mjs +19 -2
- package/dist/index175.mjs +2 -2
- package/dist/index176.mjs +2 -26
- package/dist/index177.mjs +26 -2
- package/dist/index178.mjs +2 -2
- package/dist/index179.mjs +2 -24
- package/dist/index18.mjs +37 -37
- package/dist/index180.mjs +17 -16
- package/dist/index181.mjs +23 -2
- package/dist/index183.mjs +2 -2
- package/dist/index184.mjs +2 -23
- package/dist/index185.mjs +23 -2
- package/dist/index186.mjs +2 -23
- package/dist/index187.mjs +23 -2
- package/dist/index188.mjs +2 -2
- package/dist/index19.mjs +42 -55
- package/dist/index190.mjs +2 -23
- package/dist/index191.mjs +23 -2
- package/dist/index192.mjs +2 -23
- package/dist/index193.mjs +23 -2
- package/dist/index194.mjs +2 -2
- package/dist/index195.mjs +2 -2
- package/dist/index197.mjs +2 -2
- package/dist/index198.mjs +2 -2
- package/dist/index199.mjs +2 -2
- package/dist/index2.mjs +14 -13
- package/dist/index20.mjs +53 -30
- package/dist/index200.mjs +2 -2
- package/dist/index201.mjs +2 -127
- package/dist/index202.mjs +127 -2
- package/dist/index203.mjs +2 -74
- package/dist/index204.mjs +60 -60
- package/dist/index205.mjs +73 -30
- package/dist/index206.mjs +2 -11
- package/dist/index207.mjs +30 -3
- package/dist/index208.mjs +10 -3
- package/dist/index209.mjs +4 -13
- package/dist/index21.mjs +29 -6
- package/dist/index210.mjs +4 -7
- package/dist/index211.mjs +13 -12
- package/dist/index212.mjs +7 -5
- package/dist/index213.mjs +12 -33
- package/dist/index214.mjs +5 -31
- package/dist/index215.mjs +32 -27
- package/dist/index216.mjs +28 -58
- package/dist/index217.mjs +28 -2
- package/dist/index218.mjs +61 -2
- package/dist/index219.mjs +2 -2
- package/dist/index22.mjs +8 -21
- package/dist/index220.mjs +2 -2
- package/dist/index221.mjs +2 -2
- package/dist/index222.mjs +2 -2
- package/dist/index223.mjs +2 -2
- package/dist/index224.mjs +2 -244
- package/dist/index226.mjs +2 -33
- package/dist/index227.mjs +28 -56
- package/dist/index228.mjs +2 -25
- package/dist/index229.mjs +2 -2
- package/dist/index23.mjs +19 -30
- package/dist/index230.mjs +243 -36
- package/dist/index232.mjs +33 -2
- package/dist/index233.mjs +65 -2
- package/dist/index234.mjs +25 -2
- package/dist/index235.mjs +2 -2
- package/dist/index236.mjs +108 -2
- package/dist/index237.mjs +2 -2
- package/dist/index238.mjs +2 -108
- package/dist/index239.mjs +2 -2
- package/dist/index24.mjs +31 -18
- package/dist/index241.mjs +2 -2
- package/dist/index242.mjs +2 -2
- package/dist/index244.mjs +2 -2
- package/dist/index245.mjs +2 -4
- package/dist/index246.mjs +2 -2
- package/dist/index247.mjs +4 -2
- package/dist/index248.mjs +2 -2
- package/dist/index249.mjs +2 -18
- package/dist/index25.mjs +12 -85
- package/dist/index250.mjs +3 -47
- package/dist/index251.mjs +2 -2
- package/dist/index252.mjs +2 -2
- package/dist/index253.mjs +17 -2
- package/dist/index254.mjs +13 -2
- package/dist/index255.mjs +6 -91
- package/dist/index256.mjs +30 -2
- package/dist/index257.mjs +2 -2
- package/dist/index258.mjs +18 -3
- package/dist/index259.mjs +47 -2
- package/dist/index26.mjs +85 -12
- package/dist/index260.mjs +2 -2
- package/dist/index261.mjs +2 -17
- package/dist/index262.mjs +2 -13
- package/dist/index263.mjs +2 -6
- package/dist/index264.mjs +91 -30
- package/dist/index265.mjs +2 -2
- package/dist/index266.mjs +2 -2
- package/dist/index268.mjs +5 -0
- package/dist/index269.mjs +5 -0
- package/dist/index27.mjs +18 -9
- package/dist/index28.mjs +9 -9
- package/dist/index29.mjs +11 -101
- package/dist/index3.mjs +104 -103
- package/dist/index30.mjs +101 -20
- package/dist/index31.mjs +20 -65
- package/dist/index32.mjs +66 -96
- package/dist/index33.mjs +93 -16
- package/dist/index34.mjs +13 -13
- package/dist/index35.mjs +17 -9
- package/dist/index36.mjs +9 -9
- package/dist/index37.mjs +10 -122
- package/dist/index38.mjs +116 -18
- package/dist/index39.mjs +342 -1386
- package/dist/index4.mjs +1 -1
- package/dist/index40.mjs +25 -2
- package/dist/index41.mjs +1425 -49
- package/dist/index42.mjs +2 -51
- package/dist/index43.mjs +60 -33
- package/dist/index44.mjs +49 -13
- package/dist/index45.mjs +32 -2262
- package/dist/index46.mjs +15 -36
- package/dist/index47.mjs +2261 -42
- package/dist/index48.mjs +36 -99
- package/dist/index49.mjs +43 -96
- package/dist/index5.mjs +110 -15
- package/dist/index50.mjs +99 -81
- package/dist/index51.mjs +93 -57
- package/dist/index52.mjs +54 -68
- package/dist/index53.mjs +58 -62
- package/dist/index54.mjs +74 -58
- package/dist/index55.mjs +77 -15
- package/dist/index56.mjs +75 -14
- package/dist/index57.mjs +15 -59
- package/dist/index58.mjs +11 -118
- package/dist/index59.mjs +46 -112
- package/dist/index6.mjs +15 -195
- package/dist/index60.mjs +124 -23
- package/dist/index61.mjs +129 -2
- package/dist/index62.mjs +4 -22
- package/dist/index63.mjs +19 -149
- package/dist/index64.mjs +20 -71
- package/dist/index65.mjs +153 -15
- package/dist/index66.mjs +2 -63
- package/dist/index67.mjs +74 -4
- package/dist/index68.mjs +15 -2
- package/dist/index69.mjs +62 -5
- package/dist/index7.mjs +188 -101
- package/dist/index70.mjs +230 -1129
- package/dist/index71.mjs +5 -19
- package/dist/index72.mjs +127 -48
- package/dist/index73.mjs +67 -32
- package/dist/index74.mjs +87 -2
- package/dist/index75.mjs +29 -2
- package/dist/index76.mjs +9 -235
- package/dist/index77.mjs +74 -5
- package/dist/index78.mjs +3 -133
- package/dist/index79.mjs +2 -68
- package/dist/index8.mjs +103 -73
- package/dist/index80.mjs +79 -83
- package/dist/index81.mjs +52 -27
- package/dist/index82.mjs +5 -8
- package/dist/index83.mjs +4 -74
- package/dist/index84.mjs +178 -3
- package/dist/index85.mjs +53 -2
- package/dist/index86.mjs +68 -82
- package/dist/index87.mjs +2 -54
- package/dist/index88.mjs +5 -5
- package/dist/index89.mjs +1133 -4
- package/dist/index9.mjs +72 -90
- package/dist/index90.mjs +18 -177
- package/dist/index91.mjs +52 -50
- package/dist/index92.mjs +33 -69
- package/dist/index93.mjs +2 -34
- package/dist/index94.mjs +31 -40
- package/dist/index95.mjs +43 -2
- package/dist/index96.mjs +2 -28
- package/dist/index97.mjs +2 -18
- package/dist/index98.mjs +26 -213
- package/dist/index99.mjs +13 -175
- package/dist/providers/StorefrontProvider.d.ts.map +1 -1
- package/dist/providers/TikTokPixelProvider.d.ts +22 -0
- package/dist/providers/TikTokPixelProvider.d.ts.map +1 -0
- package/package.json +3 -2
- package/src/components/Checkout.tsx +1 -0
- package/src/contexts/CartContext.tsx +17 -6
- package/src/hooks/usePaystackPayment.ts +8 -1
- package/src/index.ts +5 -0
- package/src/providers/StorefrontProvider.tsx +11 -8
- package/src/providers/TikTokPixelProvider.tsx +226 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instockng/storefront-ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.33",
|
|
4
4
|
"description": "Pre-built UI components for OMS e-commerce sites",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -45,11 +45,12 @@
|
|
|
45
45
|
"author": "Ola Wale",
|
|
46
46
|
"license": "MIT",
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@instockng/api-client": "^1.0.
|
|
48
|
+
"@instockng/api-client": "^1.0.16",
|
|
49
49
|
"class-variance-authority": "^0.7.1",
|
|
50
50
|
"clsx": "^2.1.0",
|
|
51
51
|
"react-facebook-pixel": "^1.0.4",
|
|
52
52
|
"tailwind-merge": "^2.2.0",
|
|
53
|
+
"tiktok-pixel": "^2.0.3",
|
|
53
54
|
"yup": "^1.7.1"
|
|
54
55
|
},
|
|
55
56
|
"peerDependencies": {
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
} from '@instockng/api-client';
|
|
24
24
|
import { ShoppingCart } from '../components/ShoppingCart';
|
|
25
25
|
import { useMetaPixel } from '../providers/MetaPixelProvider';
|
|
26
|
+
import { useTikTokPixel } from '../providers/TikTokPixelProvider';
|
|
26
27
|
import { getFbCookies } from '../lib/utils';
|
|
27
28
|
|
|
28
29
|
const CART_ID_KEY = 'oms_cart_id';
|
|
@@ -95,7 +96,10 @@ export function CartProvider({ children, brandSlug, initialCartId, shoppingCartP
|
|
|
95
96
|
const isHandlingErrorRef = useRef(false);
|
|
96
97
|
|
|
97
98
|
// Get Meta Pixel tracking methods
|
|
98
|
-
const { trackAddToCart, trackInitiateCheckout } = useMetaPixel();
|
|
99
|
+
const { trackAddToCart: trackMetaAddToCart, trackInitiateCheckout: trackMetaInitiateCheckout } = useMetaPixel();
|
|
100
|
+
|
|
101
|
+
// Get TikTok Pixel tracking methods
|
|
102
|
+
const { trackAddToCart: trackTikTokAddToCart, trackInitiateCheckout: trackTikTokInitiateCheckout } = useTikTokPixel();
|
|
99
103
|
|
|
100
104
|
// Set mounted flag on client
|
|
101
105
|
useEffect(() => {
|
|
@@ -256,14 +260,18 @@ export function CartProvider({ children, brandSlug, initialCartId, shoppingCartP
|
|
|
256
260
|
const eventID = `cart_${cartId}_item_${addedItem.id}`;
|
|
257
261
|
|
|
258
262
|
// Track AddToCart event with Meta Pixel and matching event ID
|
|
259
|
-
|
|
263
|
+
trackMetaAddToCart(productSlug, productName, price, quantity, eventID);
|
|
264
|
+
|
|
265
|
+
// Track AddToCart event with TikTok Pixel and matching event ID
|
|
266
|
+
trackTikTokAddToCart(productSlug, productName, price, quantity, eventID);
|
|
260
267
|
} else {
|
|
261
268
|
// Fallback without event ID if item not found
|
|
262
|
-
|
|
269
|
+
trackMetaAddToCart(productSlug, productName, price, quantity);
|
|
270
|
+
trackTikTokAddToCart(productSlug, productName, price, quantity);
|
|
263
271
|
}
|
|
264
272
|
},
|
|
265
273
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
266
|
-
[cartId,
|
|
274
|
+
[cartId, trackMetaAddToCart, trackTikTokAddToCart]
|
|
267
275
|
);
|
|
268
276
|
|
|
269
277
|
const updateItem = useCallback(
|
|
@@ -335,8 +343,11 @@ export function CartProvider({ children, brandSlug, initialCartId, shoppingCartP
|
|
|
335
343
|
const eventID = `cart_${cartId}_checkout`;
|
|
336
344
|
|
|
337
345
|
// Track InitiateCheckout event with Meta Pixel
|
|
338
|
-
|
|
339
|
-
|
|
346
|
+
trackMetaInitiateCheckout(cartTotal, itemCount, eventID);
|
|
347
|
+
|
|
348
|
+
// Track InitiateCheckout event with TikTok Pixel
|
|
349
|
+
trackTikTokInitiateCheckout(cartTotal, itemCount, eventID);
|
|
350
|
+
}, [cart, cartId, trackMetaInitiateCheckout, trackTikTokInitiateCheckout]);
|
|
340
351
|
|
|
341
352
|
const value: CartContextValue = {
|
|
342
353
|
cart: cart || null,
|
|
@@ -48,12 +48,14 @@ export interface PaystackResponse {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
export interface UsePaystackPaymentOptions {
|
|
51
|
+
isOpen: boolean;
|
|
51
52
|
publicKey: string;
|
|
52
53
|
onSuccess?: (response: PaystackResponse) => void;
|
|
53
54
|
onClose?: () => void;
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
export function usePaystackPayment({
|
|
58
|
+
isOpen,
|
|
57
59
|
publicKey,
|
|
58
60
|
onSuccess,
|
|
59
61
|
onClose,
|
|
@@ -64,6 +66,11 @@ export function usePaystackPayment({
|
|
|
64
66
|
|
|
65
67
|
// Load Paystack Inline script
|
|
66
68
|
useEffect(() => {
|
|
69
|
+
|
|
70
|
+
if (!isOpen) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
67
74
|
// Check if script is already loaded
|
|
68
75
|
if (window.PaystackPop) {
|
|
69
76
|
setIsLoaded(true);
|
|
@@ -93,7 +100,7 @@ export function usePaystackPayment({
|
|
|
93
100
|
return () => {
|
|
94
101
|
// Don't remove script on unmount as it can be reused
|
|
95
102
|
};
|
|
96
|
-
}, []);
|
|
103
|
+
}, [isOpen]);
|
|
97
104
|
|
|
98
105
|
const initializePayment = useCallback(
|
|
99
106
|
(config: Omit<PaystackConfig, 'key' | 'callback' | 'onClose'>) => {
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,11 @@ export { CartProvider, useCart } from './contexts/CartContext';
|
|
|
14
14
|
// Export Meta Pixel tracking
|
|
15
15
|
export { useMetaPixel, MetaPixelProvider } from './providers/MetaPixelProvider';
|
|
16
16
|
export type { MetaPixelProviderProps, PurchaseItem } from './providers/MetaPixelProvider';
|
|
17
|
+
|
|
18
|
+
// Export TikTok Pixel tracking
|
|
19
|
+
export { useTikTokPixel, TikTokPixelProvider } from './providers/TikTokPixelProvider';
|
|
20
|
+
|
|
21
|
+
// Export page tracking hook
|
|
17
22
|
export { usePageTracking } from './hooks/usePageTracking';
|
|
18
23
|
|
|
19
24
|
// Export main components
|
|
@@ -29,6 +29,7 @@ import { ReactNode } from 'react';
|
|
|
29
29
|
import { ApiClientProvider, useGetBrand } from '@instockng/api-client';
|
|
30
30
|
import { CartProvider, CartProviderProps } from '../contexts/CartContext';
|
|
31
31
|
import { MetaPixelProvider } from './MetaPixelProvider';
|
|
32
|
+
import { TikTokPixelProvider } from './TikTokPixelProvider';
|
|
32
33
|
|
|
33
34
|
export interface StorefrontProviderProps {
|
|
34
35
|
/** Your children components */
|
|
@@ -44,7 +45,7 @@ export interface StorefrontProviderProps {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
/**
|
|
47
|
-
* Internal component that fetches brand config and wraps children with MetaPixelProvider
|
|
48
|
+
* Internal component that fetches brand config and wraps children with MetaPixelProvider and TikTokPixelProvider
|
|
48
49
|
*/
|
|
49
50
|
function StorefrontProviderInner({
|
|
50
51
|
children,
|
|
@@ -56,13 +57,15 @@ function StorefrontProviderInner({
|
|
|
56
57
|
|
|
57
58
|
return (
|
|
58
59
|
<MetaPixelProvider pixelId={brand?.metaPixelId}>
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
<TikTokPixelProvider pixelId={brand?.tiktokPixelId}>
|
|
61
|
+
<CartProvider
|
|
62
|
+
brandSlug={brandSlug}
|
|
63
|
+
initialCartId={initialCartId}
|
|
64
|
+
shoppingCartProps={shoppingCartProps}
|
|
65
|
+
>
|
|
66
|
+
{children}
|
|
67
|
+
</CartProvider>
|
|
68
|
+
</TikTokPixelProvider>
|
|
66
69
|
</MetaPixelProvider>
|
|
67
70
|
);
|
|
68
71
|
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React, {
|
|
4
|
+
createContext,
|
|
5
|
+
useContext,
|
|
6
|
+
useEffect,
|
|
7
|
+
useState,
|
|
8
|
+
type ReactNode,
|
|
9
|
+
} from 'react';
|
|
10
|
+
|
|
11
|
+
interface TikTokPixelContextType {
|
|
12
|
+
track: (event: string, data?: Record<string, unknown>, eventID?: string) => void;
|
|
13
|
+
trackPageView: () => void;
|
|
14
|
+
trackProductView: (
|
|
15
|
+
productId: string,
|
|
16
|
+
productName: string,
|
|
17
|
+
price: number,
|
|
18
|
+
eventID?: string
|
|
19
|
+
) => void;
|
|
20
|
+
trackAddToCart: (
|
|
21
|
+
productId: string,
|
|
22
|
+
productName: string,
|
|
23
|
+
price: number,
|
|
24
|
+
quantity: number,
|
|
25
|
+
eventID?: string
|
|
26
|
+
) => void;
|
|
27
|
+
trackInitiateCheckout: (cartTotal: number, itemCount: number, eventID?: string) => void;
|
|
28
|
+
trackPurchase: (
|
|
29
|
+
orderTotal: number,
|
|
30
|
+
currency: string,
|
|
31
|
+
orderId: string,
|
|
32
|
+
items: Array<{ id: string; quantity: number; item_price: number }>,
|
|
33
|
+
eventID?: string
|
|
34
|
+
) => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const TikTokPixelContext = createContext<TikTokPixelContextType | undefined>(undefined);
|
|
38
|
+
|
|
39
|
+
interface TikTokPixelProviderProps {
|
|
40
|
+
children: ReactNode;
|
|
41
|
+
pixelId?: string;
|
|
42
|
+
debug?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let ttqInstance: any = null;
|
|
46
|
+
|
|
47
|
+
export function TikTokPixelProvider({
|
|
48
|
+
children,
|
|
49
|
+
pixelId,
|
|
50
|
+
debug = false,
|
|
51
|
+
}: TikTokPixelProviderProps) {
|
|
52
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
// Only run on client side
|
|
56
|
+
if (typeof window === 'undefined') return;
|
|
57
|
+
if (!pixelId) {
|
|
58
|
+
if (debug) {
|
|
59
|
+
console.log('TikTok Pixel ID not provided. Tracking disabled.');
|
|
60
|
+
}
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Initialize TikTok Pixel
|
|
65
|
+
const initTikTokPixel = async () => {
|
|
66
|
+
try {
|
|
67
|
+
// Dynamically import tiktok-pixel to avoid SSR issues
|
|
68
|
+
const TikTokPixel = (await import('tiktok-pixel')).default;
|
|
69
|
+
|
|
70
|
+
// Initialize pixel
|
|
71
|
+
TikTokPixel.init(pixelId, {}, { debug });
|
|
72
|
+
|
|
73
|
+
// Track initial page view
|
|
74
|
+
TikTokPixel.pageView();
|
|
75
|
+
|
|
76
|
+
ttqInstance = TikTokPixel;
|
|
77
|
+
setIsInitialized(true);
|
|
78
|
+
|
|
79
|
+
if (debug) {
|
|
80
|
+
console.log('TikTok Pixel initialized:', pixelId);
|
|
81
|
+
}
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error('Failed to initialize TikTok Pixel:', error);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
initTikTokPixel();
|
|
88
|
+
}, [pixelId, debug]);
|
|
89
|
+
|
|
90
|
+
const track = (event: string, data?: Record<string, unknown>, eventID?: string) => {
|
|
91
|
+
if (!isInitialized || !ttqInstance) {
|
|
92
|
+
if (debug) {
|
|
93
|
+
console.log('TikTok Pixel not initialized. Event not tracked:', event);
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
const eventData = eventID ? { ...data, event_id: eventID } : data;
|
|
100
|
+
ttqInstance.track(event, eventData);
|
|
101
|
+
|
|
102
|
+
if (debug) {
|
|
103
|
+
console.log('TikTok Pixel tracked event:', event, eventData);
|
|
104
|
+
}
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.error('Failed to track TikTok Pixel event:', error);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const trackPageView = () => {
|
|
111
|
+
if (!isInitialized || !ttqInstance) return;
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
ttqInstance.pageView();
|
|
115
|
+
|
|
116
|
+
if (debug) {
|
|
117
|
+
console.log('TikTok Pixel tracked page view');
|
|
118
|
+
}
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error('Failed to track TikTok Pixel page view:', error);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const trackProductView = (
|
|
125
|
+
productId: string,
|
|
126
|
+
productName: string,
|
|
127
|
+
price: number,
|
|
128
|
+
eventID?: string
|
|
129
|
+
) => {
|
|
130
|
+
track(
|
|
131
|
+
'ViewContent',
|
|
132
|
+
{
|
|
133
|
+
content_type: 'product',
|
|
134
|
+
content_id: productId,
|
|
135
|
+
content_name: productName,
|
|
136
|
+
price: price,
|
|
137
|
+
currency: 'NGN',
|
|
138
|
+
},
|
|
139
|
+
eventID
|
|
140
|
+
);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const trackAddToCart = (
|
|
144
|
+
productId: string,
|
|
145
|
+
productName: string,
|
|
146
|
+
price: number,
|
|
147
|
+
quantity: number,
|
|
148
|
+
eventID?: string
|
|
149
|
+
) => {
|
|
150
|
+
track(
|
|
151
|
+
'AddToCart',
|
|
152
|
+
{
|
|
153
|
+
content_type: 'product',
|
|
154
|
+
content_id: productId,
|
|
155
|
+
content_name: productName,
|
|
156
|
+
price: price,
|
|
157
|
+
quantity: quantity,
|
|
158
|
+
currency: 'NGN',
|
|
159
|
+
},
|
|
160
|
+
eventID
|
|
161
|
+
);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const trackInitiateCheckout = (
|
|
165
|
+
cartTotal: number,
|
|
166
|
+
itemCount: number,
|
|
167
|
+
eventID?: string
|
|
168
|
+
) => {
|
|
169
|
+
track(
|
|
170
|
+
'InitiateCheckout',
|
|
171
|
+
{
|
|
172
|
+
content_type: 'product',
|
|
173
|
+
value: cartTotal,
|
|
174
|
+
currency: 'NGN',
|
|
175
|
+
num_items: itemCount,
|
|
176
|
+
},
|
|
177
|
+
eventID
|
|
178
|
+
);
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const trackPurchase = (
|
|
182
|
+
orderTotal: number,
|
|
183
|
+
currency: string,
|
|
184
|
+
orderId: string,
|
|
185
|
+
items: Array<{ id: string; quantity: number; item_price: number }>,
|
|
186
|
+
eventID?: string
|
|
187
|
+
) => {
|
|
188
|
+
track(
|
|
189
|
+
'CompletePayment',
|
|
190
|
+
{
|
|
191
|
+
content_type: 'product',
|
|
192
|
+
value: orderTotal,
|
|
193
|
+
currency: currency,
|
|
194
|
+
contents: items.map((item) => ({
|
|
195
|
+
content_id: item.id,
|
|
196
|
+
quantity: item.quantity,
|
|
197
|
+
price: item.item_price,
|
|
198
|
+
})),
|
|
199
|
+
},
|
|
200
|
+
eventID
|
|
201
|
+
);
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const contextValue: TikTokPixelContextType = {
|
|
205
|
+
track,
|
|
206
|
+
trackPageView,
|
|
207
|
+
trackProductView,
|
|
208
|
+
trackAddToCart,
|
|
209
|
+
trackInitiateCheckout,
|
|
210
|
+
trackPurchase,
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
return (
|
|
214
|
+
<TikTokPixelContext.Provider value={contextValue}>
|
|
215
|
+
{children}
|
|
216
|
+
</TikTokPixelContext.Provider>
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function useTikTokPixel(): TikTokPixelContextType {
|
|
221
|
+
const context = useContext(TikTokPixelContext);
|
|
222
|
+
if (context === undefined) {
|
|
223
|
+
throw new Error('useTikTokPixel must be used within a TikTokPixelProvider');
|
|
224
|
+
}
|
|
225
|
+
return context;
|
|
226
|
+
}
|