shopkit-analytics 1.1.3 → 1.2.1

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,8 +1,8 @@
1
1
  import {
2
2
  initTracking,
3
3
  initializeEventTracking
4
- } from "../chunk-ASHIIHZ4.mjs";
5
- import "../chunk-T4CBWUTQ.mjs";
4
+ } from "../chunk-ZTIVTB5J.mjs";
5
+ import "../chunk-YJE5NOFF.mjs";
6
6
  import "../chunk-2DA66EMD.mjs";
7
7
  import "../chunk-UFDN3A6M.mjs";
8
8
  import {
package/dist/index.d.mts CHANGED
@@ -3,8 +3,8 @@ import { G as GoogleAdapterConfig, M as MultiPixelAdapterConfig, a as MoengageAd
3
3
  export { B as BaseAdapter, c as GoogleAdapter, g as Logger, d as MoengageAdapter, b as MultiPixelAdapter, e as PostHogAdapter, f as ShopifyAdapter, i as createAdapterLogger, h as createLogger, l as logger } from './index-fYvOG_to.mjs';
4
4
  import { T as TrackingAdapter } from './subscriber-90r_t90W.mjs';
5
5
  export { I as IAdapterParams, b as IBaseAdapterParams, a as TAdapterParams, e as eventSubscriber } from './subscriber-90r_t90W.mjs';
6
- import { s as AffiliateConfig } from './affiliate-tracker-B9nV3E9y.mjs';
7
- export { a as AffiliateData, A as AffiliateParams, b as AffiliateTracker, c as AffiliateTrackerProps, h as captureAffiliateParams, j as clearAffiliateParams, i as getAffiliateParams, o as getAffiliateSource, n as hasAffiliateData, e as useAffiliateSource, u as useAffiliateTracker, d as useHasAffiliateData } from './affiliate-tracker-B9nV3E9y.mjs';
6
+ import { A as AffiliateConfig } from './affiliate-tracker-BgHwibPv.mjs';
7
+ export { k as AffiliateData, j as AffiliateParams, a as AffiliateTracker, i as AffiliateTrackerProps, d as captureAffiliateParams, e as clearAffiliateParams, g as getAffiliateParams, f as getAffiliateSource, h as hasAffiliateData, c as useAffiliateSource, u as useAffiliateTracker, b as useHasAffiliateData } from './affiliate-tracker-BgHwibPv.mjs';
8
8
  export { BaseEvent, EventType, IAddPaymentInfoEvent, IAddToCartEvent, IBeginCheckoutEvent, ICartViewedEvent, ICustomEvent, IPageViewEvent, IPurchaseEvent, IRemoveFromCartEvent, ISearchEvent, IShopifyPageViewEvent, ISpecificEvent, IUserLoginEvent, IUserSignupEvent, IViewContentEvent, IViewSearchResultsEvent, IViewedProductEvent, TEvent } from './types.mjs';
9
9
  export { eventPublisher, initTracking, initializeEventTracking, publishEvent } from './events/index.mjs';
10
10
  export { E as ExperimentData, P as PRIMA_EXPERIMENT_COOKIES, a as PRIMA_EXPERIMENT_COOKIE_NAMES } from './types-BBZbvq9-.mjs';
@@ -102,125 +102,6 @@ interface ShopkitAnalyticsProps {
102
102
  */
103
103
  declare const ShopkitAnalytics: React.FC<ShopkitAnalyticsProps>;
104
104
 
105
- /**
106
- * Facebook CAPI Service
107
- * Core business logic for Facebook Conversion API integration
108
- * Reusable across multiple projects
109
- *
110
- * Handles:
111
- * - Rate limiting
112
- * - Event ID generation
113
- * - fbc/fbp extraction
114
- * - Event formatting
115
- * - Retry logic with exponential backoff
116
- * - Request validation
117
- * - Timeout handling
118
- * - PII hashing (IP, email, phone, names)
119
- */
120
- /**
121
- * Facebook CAPI Configuration
122
- */
123
- interface FacebookCAPIConfig {
124
- pixelId: string;
125
- accessToken: string;
126
- baseUrl: string;
127
- testEventCode?: string;
128
- }
129
- /**
130
- * CAPI Event Structure
131
- */
132
- interface CAPIEvent {
133
- event_name: string;
134
- event_time: number;
135
- event_id: string;
136
- action_source: "website" | "app";
137
- user_data: {
138
- client_ip_address?: string;
139
- client_user_agent?: string;
140
- fbc?: string;
141
- fbp?: string;
142
- em?: string;
143
- ph?: string;
144
- fn?: string;
145
- ln?: string;
146
- country?: string;
147
- st?: string;
148
- zp?: string;
149
- db?: string;
150
- external_id?: string;
151
- };
152
- custom_data: Record<string, any>;
153
- }
154
- /**
155
- * Rate Limiter - tracks requests per IP address
156
- * In-memory implementation (can be extended with Redis)
157
- */
158
- declare class RateLimiter {
159
- private store;
160
- private readonly limit;
161
- private readonly window;
162
- constructor(requestsPerMinute?: number);
163
- check(ip: string): {
164
- allowed: boolean;
165
- remaining: number;
166
- };
167
- }
168
- /**
169
- * Facebook CAPI Service
170
- * Core business logic for CAPI integration
171
- */
172
- declare class FacebookCAPIService {
173
- private rateLimiter;
174
- private readonly maxRetries;
175
- private readonly baseDelay;
176
- private readonly timeout;
177
- private readonly debug;
178
- /**
179
- * Check if request is within rate limits
180
- */
181
- checkRateLimit(clientIp: string): {
182
- allowed: boolean;
183
- remaining: number;
184
- };
185
- /**
186
- * Generate a unique event ID for deduplication
187
- */
188
- generateEventId(eventName: string): string;
189
- /**
190
- * Extract fbc cookie from request headers
191
- */
192
- extractFbcFromRequest(request: Request): string | undefined;
193
- /**
194
- * Get client IP address from request headers
195
- */
196
- getClientIpAddress(request: Request): string | undefined;
197
- /**
198
- * Convert event to Facebook CAPI format with optional PII hashing
199
- * Note: This method is now async to support SHA-256 IP hashing
200
- */
201
- convertToCapiEvent(eventName: string, eventId: string, timestamp: number | undefined, enhancedParams: any, userInfo: any): Promise<CAPIEvent>;
202
- /**
203
- * Send event to Facebook CAPI with retry logic
204
- */
205
- sendToFacebook(config: FacebookCAPIConfig, capiEvent: CAPIEvent): Promise<{
206
- success: boolean;
207
- data?: any;
208
- error?: string;
209
- pixelId: string;
210
- }>;
211
- /**
212
- * Validate request body
213
- */
214
- validateRequestBody(eventName: string, enhancedParams: any, bodySize: number): {
215
- valid: boolean;
216
- error?: string;
217
- };
218
- }
219
- /**
220
- * Singleton instance of the service
221
- */
222
- declare const facebookCAPIService: FacebookCAPIService;
223
-
224
105
  /**
225
106
  * Component to initialize Shopify Analytics cookies
226
107
  * This component handles the useShopifyCookies hook which must be used in a React component
@@ -230,4 +111,4 @@ interface ShopifyAnalyticsScriptProps {
230
111
  }
231
112
  declare function ShopifyAnalyticsScript({ domain, }: ShopifyAnalyticsScriptProps): null;
232
113
 
233
- export { AffiliateConfig, type CAPIEvent, type FacebookCAPIConfig, FacebookCAPIService, GoogleAdapterConfig, LoggerConfig, MoengageAdapterConfig, MultiPixelAdapterConfig, PostHogAdapterConfig, RateLimiter, ShopifyAdapterConfig, ShopifyAnalyticsScript, ShopkitAnalytics, type ShopkitAnalyticsConfig, type ShopkitAnalyticsProps, TrackingAdapter, ShopkitAnalytics as default, facebookCAPIService };
114
+ export { AffiliateConfig, GoogleAdapterConfig, LoggerConfig, MoengageAdapterConfig, MultiPixelAdapterConfig, PostHogAdapterConfig, ShopifyAdapterConfig, ShopifyAnalyticsScript, ShopkitAnalytics, type ShopkitAnalyticsConfig, type ShopkitAnalyticsProps, TrackingAdapter, ShopkitAnalytics as default };
package/dist/index.d.ts CHANGED
@@ -3,8 +3,8 @@ import { G as GoogleAdapterConfig, M as MultiPixelAdapterConfig, a as MoengageAd
3
3
  export { B as BaseAdapter, c as GoogleAdapter, g as Logger, d as MoengageAdapter, b as MultiPixelAdapter, e as PostHogAdapter, f as ShopifyAdapter, i as createAdapterLogger, h as createLogger, l as logger } from './index-B-TnPt4F.js';
4
4
  import { T as TrackingAdapter } from './subscriber-AtiHiP3i.js';
5
5
  export { I as IAdapterParams, b as IBaseAdapterParams, a as TAdapterParams, e as eventSubscriber } from './subscriber-AtiHiP3i.js';
6
- import { s as AffiliateConfig } from './affiliate-tracker-B9nV3E9y.js';
7
- export { a as AffiliateData, A as AffiliateParams, b as AffiliateTracker, c as AffiliateTrackerProps, h as captureAffiliateParams, j as clearAffiliateParams, i as getAffiliateParams, o as getAffiliateSource, n as hasAffiliateData, e as useAffiliateSource, u as useAffiliateTracker, d as useHasAffiliateData } from './affiliate-tracker-B9nV3E9y.js';
6
+ import { A as AffiliateConfig } from './affiliate-tracker-BgHwibPv.js';
7
+ export { k as AffiliateData, j as AffiliateParams, a as AffiliateTracker, i as AffiliateTrackerProps, d as captureAffiliateParams, e as clearAffiliateParams, g as getAffiliateParams, f as getAffiliateSource, h as hasAffiliateData, c as useAffiliateSource, u as useAffiliateTracker, b as useHasAffiliateData } from './affiliate-tracker-BgHwibPv.js';
8
8
  export { BaseEvent, EventType, IAddPaymentInfoEvent, IAddToCartEvent, IBeginCheckoutEvent, ICartViewedEvent, ICustomEvent, IPageViewEvent, IPurchaseEvent, IRemoveFromCartEvent, ISearchEvent, IShopifyPageViewEvent, ISpecificEvent, IUserLoginEvent, IUserSignupEvent, IViewContentEvent, IViewSearchResultsEvent, IViewedProductEvent, TEvent } from './types.js';
9
9
  export { eventPublisher, initTracking, initializeEventTracking, publishEvent } from './events/index.js';
10
10
  export { E as ExperimentData, P as PRIMA_EXPERIMENT_COOKIES, a as PRIMA_EXPERIMENT_COOKIE_NAMES } from './types-BBZbvq9-.js';
@@ -102,125 +102,6 @@ interface ShopkitAnalyticsProps {
102
102
  */
103
103
  declare const ShopkitAnalytics: React.FC<ShopkitAnalyticsProps>;
104
104
 
105
- /**
106
- * Facebook CAPI Service
107
- * Core business logic for Facebook Conversion API integration
108
- * Reusable across multiple projects
109
- *
110
- * Handles:
111
- * - Rate limiting
112
- * - Event ID generation
113
- * - fbc/fbp extraction
114
- * - Event formatting
115
- * - Retry logic with exponential backoff
116
- * - Request validation
117
- * - Timeout handling
118
- * - PII hashing (IP, email, phone, names)
119
- */
120
- /**
121
- * Facebook CAPI Configuration
122
- */
123
- interface FacebookCAPIConfig {
124
- pixelId: string;
125
- accessToken: string;
126
- baseUrl: string;
127
- testEventCode?: string;
128
- }
129
- /**
130
- * CAPI Event Structure
131
- */
132
- interface CAPIEvent {
133
- event_name: string;
134
- event_time: number;
135
- event_id: string;
136
- action_source: "website" | "app";
137
- user_data: {
138
- client_ip_address?: string;
139
- client_user_agent?: string;
140
- fbc?: string;
141
- fbp?: string;
142
- em?: string;
143
- ph?: string;
144
- fn?: string;
145
- ln?: string;
146
- country?: string;
147
- st?: string;
148
- zp?: string;
149
- db?: string;
150
- external_id?: string;
151
- };
152
- custom_data: Record<string, any>;
153
- }
154
- /**
155
- * Rate Limiter - tracks requests per IP address
156
- * In-memory implementation (can be extended with Redis)
157
- */
158
- declare class RateLimiter {
159
- private store;
160
- private readonly limit;
161
- private readonly window;
162
- constructor(requestsPerMinute?: number);
163
- check(ip: string): {
164
- allowed: boolean;
165
- remaining: number;
166
- };
167
- }
168
- /**
169
- * Facebook CAPI Service
170
- * Core business logic for CAPI integration
171
- */
172
- declare class FacebookCAPIService {
173
- private rateLimiter;
174
- private readonly maxRetries;
175
- private readonly baseDelay;
176
- private readonly timeout;
177
- private readonly debug;
178
- /**
179
- * Check if request is within rate limits
180
- */
181
- checkRateLimit(clientIp: string): {
182
- allowed: boolean;
183
- remaining: number;
184
- };
185
- /**
186
- * Generate a unique event ID for deduplication
187
- */
188
- generateEventId(eventName: string): string;
189
- /**
190
- * Extract fbc cookie from request headers
191
- */
192
- extractFbcFromRequest(request: Request): string | undefined;
193
- /**
194
- * Get client IP address from request headers
195
- */
196
- getClientIpAddress(request: Request): string | undefined;
197
- /**
198
- * Convert event to Facebook CAPI format with optional PII hashing
199
- * Note: This method is now async to support SHA-256 IP hashing
200
- */
201
- convertToCapiEvent(eventName: string, eventId: string, timestamp: number | undefined, enhancedParams: any, userInfo: any): Promise<CAPIEvent>;
202
- /**
203
- * Send event to Facebook CAPI with retry logic
204
- */
205
- sendToFacebook(config: FacebookCAPIConfig, capiEvent: CAPIEvent): Promise<{
206
- success: boolean;
207
- data?: any;
208
- error?: string;
209
- pixelId: string;
210
- }>;
211
- /**
212
- * Validate request body
213
- */
214
- validateRequestBody(eventName: string, enhancedParams: any, bodySize: number): {
215
- valid: boolean;
216
- error?: string;
217
- };
218
- }
219
- /**
220
- * Singleton instance of the service
221
- */
222
- declare const facebookCAPIService: FacebookCAPIService;
223
-
224
105
  /**
225
106
  * Component to initialize Shopify Analytics cookies
226
107
  * This component handles the useShopifyCookies hook which must be used in a React component
@@ -230,4 +111,4 @@ interface ShopifyAnalyticsScriptProps {
230
111
  }
231
112
  declare function ShopifyAnalyticsScript({ domain, }: ShopifyAnalyticsScriptProps): null;
232
113
 
233
- export { AffiliateConfig, type CAPIEvent, type FacebookCAPIConfig, FacebookCAPIService, GoogleAdapterConfig, LoggerConfig, MoengageAdapterConfig, MultiPixelAdapterConfig, PostHogAdapterConfig, RateLimiter, ShopifyAdapterConfig, ShopifyAnalyticsScript, ShopkitAnalytics, type ShopkitAnalyticsConfig, type ShopkitAnalyticsProps, TrackingAdapter, ShopkitAnalytics as default, facebookCAPIService };
114
+ export { AffiliateConfig, GoogleAdapterConfig, LoggerConfig, MoengageAdapterConfig, MultiPixelAdapterConfig, PostHogAdapterConfig, ShopifyAdapterConfig, ShopifyAnalyticsScript, ShopkitAnalytics, type ShopkitAnalyticsConfig, type ShopkitAnalyticsProps, TrackingAdapter, ShopkitAnalytics as default };
package/dist/index.js CHANGED
@@ -264,14 +264,12 @@ __export(src_exports, {
264
264
  AffiliateTracker: () => AffiliateTracker_default,
265
265
  BaseAdapter: () => BaseAdapter,
266
266
  EventType: () => EventType,
267
- FacebookCAPIService: () => FacebookCAPIService,
268
267
  GoogleAdapter: () => GoogleAdapter,
269
268
  MoengageAdapter: () => MoengageAdapter,
270
269
  MultiPixelAdapter: () => MultiPixelAdapter,
271
270
  PRIMA_EXPERIMENT_COOKIES: () => PRIMA_EXPERIMENT_COOKIES,
272
271
  PRIMA_EXPERIMENT_COOKIE_NAMES: () => PRIMA_EXPERIMENT_COOKIE_NAMES,
273
272
  PostHogAdapter: () => PostHogAdapter,
274
- RateLimiter: () => RateLimiter,
275
273
  ShopifyAdapter: () => ShopifyAdapter,
276
274
  ShopifyAnalyticsScript: () => ShopifyAnalyticsScript,
277
275
  ShopkitAnalytics: () => ShopkitAnalytics_default,
@@ -282,7 +280,6 @@ __export(src_exports, {
282
280
  default: () => ShopkitAnalytics_default,
283
281
  eventPublisher: () => eventPublisher,
284
282
  eventSubscriber: () => eventSubscriber,
285
- facebookCAPIService: () => facebookCAPIService,
286
283
  generateEventId: () => generateEventId,
287
284
  getAffiliateParams: () => getAffiliateParams,
288
285
  getAffiliateSource: () => getAffiliateSource,
@@ -784,12 +781,13 @@ var MultiPixelAdapter = class extends BaseAdapter {
784
781
  if (!eventName) {
785
782
  return;
786
783
  }
787
- console.log("@@@ trackClientSide", eventName, enhancedParams, {
788
- eventID: event.eventId
789
- });
790
- window.fbq("track", eventName, enhancedParams, {
791
- eventID: event.eventId
792
- });
784
+ try {
785
+ window.fbq("track", eventName, enhancedParams, {
786
+ eventID: event.eventId
787
+ });
788
+ } catch (error) {
789
+ console.error("Facebook Pixel tracking error:", error);
790
+ }
793
791
  }
794
792
  /**
795
793
  * Track event on server-side for all enabled pixels
@@ -809,14 +807,8 @@ var MultiPixelAdapter = class extends BaseAdapter {
809
807
  eventId: event.eventId,
810
808
  timestamp: event.timestamp,
811
809
  enhancedParams,
812
- userInfo: browserInfo,
813
- // Send all pixel info to the multi-pixel endpoint
814
- pixels: this.pixels.filter((pixel) => pixel.config.enableCAPI).map((pixel) => ({
815
- pixelId: pixel.config.pixelId,
816
- name: pixel.config.name
817
- }))
810
+ userInfo: browserInfo
818
811
  };
819
- console.log("@@@ trackServerSide", payload);
820
812
  const endpoint = this.getConfig("capiEndpoint", "/api/events/multi");
821
813
  const response = await fetch(endpoint, {
822
814
  method: "POST",
@@ -826,7 +818,7 @@ var MultiPixelAdapter = class extends BaseAdapter {
826
818
  body: JSON.stringify(payload)
827
819
  });
828
820
  if (!response.ok) {
829
- throw new Error(`Server-side tracking failed: ${response.status}`);
821
+ this.logger.error(`Server-side tracking failed: ${response.status}`);
830
822
  }
831
823
  } catch (error) {
832
824
  this.logger.error(
@@ -2433,332 +2425,17 @@ var ShopkitAnalytics = ({
2433
2425
  ] });
2434
2426
  };
2435
2427
  var ShopkitAnalytics_default = ShopkitAnalytics;
2436
-
2437
- // src/utils/pii-hashing.ts
2438
- async function hashString(value, normalize) {
2439
- if (!value) {
2440
- return void 0;
2441
- }
2442
- try {
2443
- const normalizedValue = normalize ? normalize(value) : value;
2444
- if (typeof crypto !== "undefined" && crypto.subtle) {
2445
- const encoder = new TextEncoder();
2446
- const data = encoder.encode(normalizedValue);
2447
- const hashBuffer = await crypto.subtle.digest("SHA-256", data);
2448
- const hashArray = Array.from(new Uint8Array(hashBuffer));
2449
- const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
2450
- return hashHex;
2451
- }
2452
- } catch (error) {
2453
- console.error("Error hashing with SHA-256:", error);
2454
- }
2455
- return fallbackHash(value);
2456
- }
2457
- async function hashIP(ip) {
2458
- return hashString(ip, (value) => value.trim());
2459
- }
2460
- function fallbackHash(value) {
2461
- let hash = 0;
2462
- if (value.length === 0) {
2463
- return "0";
2464
- }
2465
- for (let i = 0; i < value.length; i++) {
2466
- const char = value.charCodeAt(i);
2467
- hash = (hash << 5) - hash + char;
2468
- hash = hash & hash;
2469
- }
2470
- return Math.abs(hash).toString(16).padStart(16, "0");
2471
- }
2472
-
2473
- // src/services/facebook-capi.service.ts
2474
- var RateLimiter = class {
2475
- constructor(requestsPerMinute = 100) {
2476
- this.store = /* @__PURE__ */ new Map();
2477
- this.limit = requestsPerMinute;
2478
- this.window = 60 * 1e3;
2479
- }
2480
- check(ip) {
2481
- const now = Date.now();
2482
- let entry = this.store.get(ip);
2483
- if (entry && entry.resetTime < now) {
2484
- this.store.delete(ip);
2485
- entry = void 0;
2486
- }
2487
- if (!entry) {
2488
- entry = { count: 0, resetTime: now + this.window };
2489
- this.store.set(ip, entry);
2490
- }
2491
- const allowed = entry.count < this.limit;
2492
- entry.count++;
2493
- return {
2494
- allowed,
2495
- remaining: Math.max(0, this.limit - entry.count)
2496
- };
2497
- }
2498
- };
2499
- var FacebookCAPIService = class {
2500
- constructor() {
2501
- this.rateLimiter = new RateLimiter(100);
2502
- // 100 requests per minute per IP
2503
- this.maxRetries = 3;
2504
- this.baseDelay = 1e3;
2505
- // 1 second
2506
- this.timeout = 3e4;
2507
- // 30 seconds
2508
- this.debug = false;
2509
- }
2510
- // Override in consuming projects if needed
2511
- /**
2512
- * Check if request is within rate limits
2513
- */
2514
- checkRateLimit(clientIp) {
2515
- return this.rateLimiter.check(clientIp);
2516
- }
2517
- /**
2518
- * Generate a unique event ID for deduplication
2519
- */
2520
- generateEventId(eventName) {
2521
- const timestamp = Date.now();
2522
- const randomString = Math.random().toString(36).substring(2, 8);
2523
- return `${timestamp}_${randomString}_${eventName}`;
2524
- }
2525
- /**
2526
- * Extract fbc cookie from request headers
2527
- */
2528
- extractFbcFromRequest(request) {
2529
- const cookieHeader = request.headers.get("cookie");
2530
- if (!cookieHeader) return void 0;
2531
- const cookies = cookieHeader.split(";");
2532
- for (const cookie of cookies) {
2533
- const [name, value] = cookie.trim().split("=");
2534
- if (name === "_fbc") {
2535
- return value;
2536
- }
2537
- }
2538
- return void 0;
2539
- }
2540
- /**
2541
- * Get client IP address from request headers
2542
- */
2543
- getClientIpAddress(request) {
2544
- const forwarded = request.headers.get("x-forwarded-for");
2545
- const realIp = request.headers.get("x-real-ip");
2546
- const cfConnectingIp = request.headers.get("cf-connecting-ip");
2547
- return forwarded?.split(",")[0] || realIp || cfConnectingIp || void 0;
2548
- }
2549
- /**
2550
- * Convert event to Facebook CAPI format with optional PII hashing
2551
- * Note: This method is now async to support SHA-256 IP hashing
2552
- */
2553
- async convertToCapiEvent(eventName, eventId, timestamp, enhancedParams, userInfo) {
2554
- const eventTime = timestamp ? Math.floor(timestamp / 1e3) : Math.floor(Date.now() / 1e3);
2555
- let hashedIp;
2556
- if (userInfo?.clientIpAddress) {
2557
- try {
2558
- hashedIp = await hashIP(userInfo.clientIpAddress);
2559
- } catch (error) {
2560
- console.error("[Facebook CAPI] Error hashing IP:", error);
2561
- hashedIp = userInfo.clientIpAddress;
2562
- }
2563
- }
2564
- if (this.debug) {
2565
- console.log("[Facebook CAPI] Event Conversion", {
2566
- eventName,
2567
- eventId,
2568
- eventTime,
2569
- timestamp_input: timestamp,
2570
- fbp: !!userInfo?.fbp,
2571
- fbc: !!userInfo?.fbc,
2572
- ip_hashed: !!hashedIp,
2573
- pii_fields: {
2574
- em: !!userInfo?.em,
2575
- ph: !!userInfo?.ph,
2576
- fn: !!userInfo?.fn,
2577
- ln: !!userInfo?.ln
2578
- }
2579
- });
2580
- }
2581
- const capiEvent = {
2582
- event_name: eventName,
2583
- event_time: eventTime,
2584
- event_id: eventId,
2585
- action_source: "website",
2586
- user_data: {
2587
- client_ip_address: hashedIp,
2588
- client_user_agent: userInfo?.clientUserAgent,
2589
- fbc: userInfo?.fbc,
2590
- fbp: userInfo?.fbp
2591
- },
2592
- custom_data: enhancedParams
2593
- };
2594
- if (userInfo?.em) {
2595
- capiEvent.user_data.em = userInfo.em;
2596
- }
2597
- if (userInfo?.ph) {
2598
- capiEvent.user_data.ph = userInfo.ph;
2599
- }
2600
- if (userInfo?.fn) {
2601
- capiEvent.user_data.fn = userInfo.fn;
2602
- }
2603
- if (userInfo?.ln) {
2604
- capiEvent.user_data.ln = userInfo.ln;
2605
- }
2606
- if (userInfo?.country) {
2607
- capiEvent.user_data.country = userInfo.country;
2608
- }
2609
- if (userInfo?.st) {
2610
- capiEvent.user_data.st = userInfo.st;
2611
- }
2612
- if (userInfo?.zp) {
2613
- capiEvent.user_data.zp = userInfo.zp;
2614
- }
2615
- if (userInfo?.db) {
2616
- capiEvent.user_data.db = userInfo.db;
2617
- }
2618
- if (userInfo?.external_id) {
2619
- capiEvent.user_data.external_id = userInfo.external_id;
2620
- }
2621
- return capiEvent;
2622
- }
2623
- /**
2624
- * Send event to Facebook CAPI with retry logic
2625
- */
2626
- async sendToFacebook(config, capiEvent) {
2627
- for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
2628
- try {
2629
- const payload = {
2630
- data: [capiEvent],
2631
- test_event_code: config.testEventCode
2632
- };
2633
- if (this.debug) {
2634
- console.log("[Facebook CAPI] Sending to Facebook", {
2635
- pixelId: config.pixelId,
2636
- eventId: capiEvent.event_id,
2637
- eventName: capiEvent.event_name,
2638
- attempt: attempt + 1
2639
- });
2640
- }
2641
- const url = `${config.baseUrl}/${config.pixelId}/events?access_token=${config.accessToken}`;
2642
- const controller = new AbortController();
2643
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2644
- try {
2645
- const response = await fetch(url, {
2646
- method: "POST",
2647
- headers: {
2648
- "Content-Type": "application/json"
2649
- },
2650
- body: JSON.stringify(payload),
2651
- signal: controller.signal
2652
- });
2653
- clearTimeout(timeoutId);
2654
- if (!response.ok) {
2655
- if ((response.status >= 500 || response.status === 429) && attempt < this.maxRetries) {
2656
- const delay = this.baseDelay * Math.pow(2, attempt);
2657
- if (this.debug) {
2658
- console.log(`[Facebook CAPI] Retrying in ${delay}ms`, {
2659
- pixelId: config.pixelId,
2660
- status: response.status
2661
- });
2662
- }
2663
- await new Promise((resolve) => setTimeout(resolve, delay));
2664
- continue;
2665
- }
2666
- console.error(
2667
- `Facebook CAPI Error for pixel ${config.pixelId} (attempt ${attempt + 1}/${this.maxRetries + 1}):`,
2668
- { status: response.status }
2669
- );
2670
- return {
2671
- success: false,
2672
- error: `Facebook CAPI request failed: ${response.status}`,
2673
- pixelId: config.pixelId
2674
- };
2675
- }
2676
- const result = await response.json();
2677
- if (this.debug) {
2678
- console.log(
2679
- `Facebook CAPI: Events sent successfully to pixel ${config.pixelId}`,
2680
- {
2681
- events_received: result.events_received
2682
- }
2683
- );
2684
- }
2685
- return {
2686
- success: true,
2687
- data: result,
2688
- pixelId: config.pixelId
2689
- };
2690
- } finally {
2691
- clearTimeout(timeoutId);
2692
- }
2693
- } catch (error) {
2694
- const errorMessage = error instanceof Error ? error.message : String(error);
2695
- if (attempt < this.maxRetries) {
2696
- const delay = this.baseDelay * Math.pow(2, attempt);
2697
- if (this.debug) {
2698
- console.log(`[Facebook CAPI] Retrying in ${delay}ms after error`, {
2699
- pixelId: config.pixelId,
2700
- error: errorMessage
2701
- });
2702
- }
2703
- await new Promise((resolve) => setTimeout(resolve, delay));
2704
- continue;
2705
- }
2706
- console.error(
2707
- `Facebook CAPI Network Error for pixel ${config.pixelId} (attempt ${attempt + 1}/${this.maxRetries + 1}):`,
2708
- { error: errorMessage }
2709
- );
2710
- return {
2711
- success: false,
2712
- error: `Network error: ${errorMessage}`,
2713
- pixelId: config.pixelId
2714
- };
2715
- }
2716
- }
2717
- return {
2718
- success: false,
2719
- error: "Failed after all retry attempts",
2720
- pixelId: config.pixelId
2721
- };
2722
- }
2723
- /**
2724
- * Validate request body
2725
- */
2726
- validateRequestBody(eventName, enhancedParams, bodySize) {
2727
- if (!eventName || !enhancedParams) {
2728
- return {
2729
- valid: false,
2730
- error: "eventName and enhancedParams are required"
2731
- };
2732
- }
2733
- if (bodySize > 1024 * 1024) {
2734
- return {
2735
- valid: false,
2736
- error: "Request body too large (max 1MB)"
2737
- };
2738
- }
2739
- if (!/^[a-zA-Z0-9_]+$/.test(eventName)) {
2740
- return {
2741
- valid: false,
2742
- error: "eventName must contain only alphanumeric characters and underscores"
2743
- };
2744
- }
2745
- return { valid: true };
2746
- }
2747
- };
2748
- var facebookCAPIService = new FacebookCAPIService();
2749
2428
  // Annotate the CommonJS export names for ESM import in node:
2750
2429
  0 && (module.exports = {
2751
2430
  AffiliateTracker,
2752
2431
  BaseAdapter,
2753
2432
  EventType,
2754
- FacebookCAPIService,
2755
2433
  GoogleAdapter,
2756
2434
  MoengageAdapter,
2757
2435
  MultiPixelAdapter,
2758
2436
  PRIMA_EXPERIMENT_COOKIES,
2759
2437
  PRIMA_EXPERIMENT_COOKIE_NAMES,
2760
2438
  PostHogAdapter,
2761
- RateLimiter,
2762
2439
  ShopifyAdapter,
2763
2440
  ShopifyAnalyticsScript,
2764
2441
  ShopkitAnalytics,
@@ -2768,7 +2445,6 @@ var facebookCAPIService = new FacebookCAPIService();
2768
2445
  createLogger,
2769
2446
  eventPublisher,
2770
2447
  eventSubscriber,
2771
- facebookCAPIService,
2772
2448
  generateEventId,
2773
2449
  getAffiliateParams,
2774
2450
  getAffiliateSource,