shopkit-analytics 1.1.2 → 1.1.3

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/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  initTracking,
3
3
  initializeEventTracking
4
- } from "./chunk-ANVCP4FV.mjs";
4
+ } from "./chunk-ASHIIHZ4.mjs";
5
5
  import {
6
6
  AffiliateTracker_default,
7
7
  captureAffiliateParams,
@@ -16,8 +16,6 @@ import {
16
16
  import {
17
17
  BaseAdapter,
18
18
  GoogleAdapter,
19
- KwikCheckoutAdapter,
20
- KwikPassAdapter,
21
19
  MoengageAdapter,
22
20
  MultiPixelAdapter,
23
21
  PostHogAdapter,
@@ -25,7 +23,7 @@ import {
25
23
  createAdapterLogger,
26
24
  createLogger,
27
25
  logger
28
- } from "./chunk-EBZU3HYF.mjs";
26
+ } from "./chunk-T4CBWUTQ.mjs";
29
27
  import {
30
28
  PRIMA_EXPERIMENT_COOKIES,
31
29
  PRIMA_EXPERIMENT_COOKIE_NAMES,
@@ -38,7 +36,7 @@ import {
38
36
  } from "./chunk-UFDN3A6M.mjs";
39
37
  import {
40
38
  EventType
41
- } from "./chunk-FXJKI3KV.mjs";
39
+ } from "./chunk-CYSLR6EI.mjs";
42
40
  import {
43
41
  eventPublisher,
44
42
  eventSubscriber,
@@ -170,20 +168,6 @@ var ShopkitAnalytics = ({
170
168
  adapters.push(shopifyAdapter);
171
169
  logger2.info("Added Shopify Analytics adapter");
172
170
  }
173
- if (config.kwikpass) {
174
- const kwikpassAdapter = new KwikPassAdapter(
175
- addLoggerConfig(config.kwikpass)
176
- );
177
- adapters.push(kwikpassAdapter);
178
- logger2.info("Added KwikPass Analytics adapter");
179
- }
180
- if (config.kwikcheckout) {
181
- const kwikcheckoutAdapter = new KwikCheckoutAdapter(
182
- addLoggerConfig(config.kwikcheckout)
183
- );
184
- adapters.push(kwikcheckoutAdapter);
185
- logger2.info("Added KwikCheckout Analytics adapter");
186
- }
187
171
  if (config.customAdapters) {
188
172
  adapters.push(...config.customAdapters);
189
173
  logger2.info(`Added ${config.customAdapters.length} custom adapters`);
@@ -538,8 +522,6 @@ export {
538
522
  EventType,
539
523
  FacebookCAPIService,
540
524
  GoogleAdapter,
541
- KwikCheckoutAdapter,
542
- KwikPassAdapter,
543
525
  MoengageAdapter,
544
526
  MultiPixelAdapter,
545
527
  PRIMA_EXPERIMENT_COOKIES,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ShopkitAnalytics.tsx","../src/shopify/ShopifyAnalyticsScript.tsx","../src/utils/pii-hashing.ts","../src/services/facebook-capi.service.ts"],"sourcesContent":["\"use client\";\n\n/**\n * ShopkitAnalytics Component\n *\n * Main analytics provider component that initializes and manages\n * all configured analytics adapters.\n *\n * @module @shopkit/analytics\n */\n\nimport React, { useEffect } from \"react\";\nimport { initializeEventTracking } from \"./events/init\";\nimport { AffiliateTracker } from \"./affiliate\";\nimport { createLogger, type LoggerConfig } from \"./logger\";\nimport {\n GoogleAdapter,\n MultiPixelAdapter,\n MoengageAdapter,\n PostHogAdapter,\n ShopifyAdapter,\n KwikPassAdapter,\n KwikCheckoutAdapter,\n} from \"./adapters\";\nimport type {\n GoogleAdapterConfig,\n MultiPixelAdapterConfig,\n MoengageAdapterConfig,\n PostHogAdapterConfig,\n ShopifyAdapterConfig,\n KwikPassConfig,\n KwikCheckoutConfig,\n} from \"./adapters\";\nimport type { TrackingAdapter } from \"./events/subscriber\";\nimport type { AffiliateConfig } from \"./affiliate/types\";\nimport { ShopifyAnalyticsScript } from \"./shopify/ShopifyAnalyticsScript\";\n\n/**\n * Configuration for ShopkitAnalytics component\n *\n * @example\n * ```typescript\n * const config: ShopkitAnalyticsConfig = {\n * googleAnalytics: { measurementId: 'G-XXXXXX' },\n * facebookPixel: { pixelId: '123456789' },\n * posthog: { apiKey: 'phc_xxx', apiHost: 'https://app.posthog.com' },\n * logger: { enabled: true, level: 'info' },\n * };\n * ```\n */\nexport interface ShopkitAnalyticsConfig {\n // Analytics Adapters\n googleAnalytics?: GoogleAdapterConfig;\n facebookMultiPixel?: MultiPixelAdapterConfig;\n moengage?: MoengageAdapterConfig;\n posthog?: PostHogAdapterConfig;\n shopify?: ShopifyAdapterConfig;\n kwikpass?: KwikPassConfig;\n kwikcheckout?: KwikCheckoutConfig;\n customAdapters?: TrackingAdapter[];\n\n // Affiliate Tracking\n affiliate?: {\n enabled?: boolean;\n config?: Partial<AffiliateConfig>;\n autoCapture?: boolean;\n };\n\n // Logger Settings\n logger?: LoggerConfig;\n\n // General Settings (deprecated - use logger.enabled instead)\n enableDebugLogs?: boolean;\n autoInitialize?: boolean;\n}\n\n/**\n * Props for ShopkitAnalytics component\n */\nexport interface ShopkitAnalyticsProps {\n /** Analytics configuration object */\n config: ShopkitAnalyticsConfig;\n /** Optional children to render */\n children?: React.ReactNode;\n /** Callback when analytics initialization completes */\n onInitialized?: () => void;\n /** Callback when an error occurs during initialization */\n onError?: (error: Error) => void;\n}\n\n/**\n * ShopkitAnalytics Component\n *\n * The main analytics provider that initializes all configured tracking adapters\n * and sets up event publishing infrastructure.\n *\n * Place this component in your app's root layout to enable analytics tracking\n * throughout your application.\n *\n * @param props - Component props\n * @returns React component with analytics initialization and affiliate tracking\n *\n * @example\n * ```typescript\n * // In your root layout\n * import { ShopkitAnalytics } from '@shopkit/analytics';\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html>\n * <body>\n * <ShopkitAnalytics\n * config={{\n * googleAnalytics: { measurementId: 'G-XXXXXX' },\n * facebookPixel: { pixelId: '123456789' },\n * }}\n * onInitialized={() => console.log('Analytics ready')}\n * onError={(err) => console.error('Analytics error:', err)}\n * >\n * {children}\n * </ShopkitAnalytics>\n * </body>\n * </html>\n * );\n * }\n * ```\n */\nconst ShopkitAnalytics: React.FC<ShopkitAnalyticsProps> = ({\n config,\n children,\n onInitialized,\n onError,\n}) => {\n useEffect(() => {\n const initializeAnalytics = async () => {\n if (config.autoInitialize === false) return;\n\n // Create logger instance\n const loggerConfig: LoggerConfig = {\n enabled: config.logger?.enabled ?? config.enableDebugLogs ?? true,\n level: config.logger?.level ?? \"info\",\n name: \"@shopkit/analytics\",\n prettyPrint: config.logger?.prettyPrint ?? false,\n };\n\n const logger = createLogger(loggerConfig);\n\n try {\n logger.info(\"Starting initialization...\");\n\n const adapters: TrackingAdapter[] = [];\n\n // Helper function to add logger config to adapter config\n const addLoggerConfig = (adapterConfig: any) => ({\n ...adapterConfig,\n enableDebugLogs: loggerConfig.enabled,\n logLevel: loggerConfig.level,\n });\n\n // Google Analytics 4\n if (config.googleAnalytics) {\n const gaAdapter = new GoogleAdapter(\n addLoggerConfig(config.googleAnalytics),\n );\n adapters.push(gaAdapter);\n logger.info(\"Added Google Analytics adapter\");\n }\n\n // Facebook Multi-Pixel\n if (config.facebookMultiPixel) {\n const multiPixelAdapter = new MultiPixelAdapter(\n addLoggerConfig(config.facebookMultiPixel),\n );\n adapters.push(multiPixelAdapter);\n logger.info(\n `Added Facebook Multi-Pixel adapter with ${config.facebookMultiPixel.pixels.length} pixels`,\n );\n }\n\n // MoEngage\n if (config.moengage) {\n const moengageAdapter = new MoengageAdapter(\n addLoggerConfig(config.moengage),\n );\n adapters.push(moengageAdapter);\n logger.info(\"Added MoEngage adapter\");\n }\n\n // PostHog\n if (config.posthog) {\n const posthogAdapter = new PostHogAdapter(\n addLoggerConfig(config.posthog),\n );\n adapters.push(posthogAdapter);\n logger.info(\"Added PostHog adapter\");\n }\n\n // Shopify Analytics\n if (config.shopify) {\n const shopifyAdapter = new ShopifyAdapter(\n addLoggerConfig(config.shopify),\n );\n adapters.push(shopifyAdapter);\n logger.info(\"Added Shopify Analytics adapter\");\n }\n\n // KwikPass Analytics\n if (config.kwikpass) {\n const kwikpassAdapter = new KwikPassAdapter(\n addLoggerConfig(config.kwikpass),\n );\n adapters.push(kwikpassAdapter);\n logger.info(\"Added KwikPass Analytics adapter\");\n }\n\n // KwikCheckout Analytics\n if (config.kwikcheckout) {\n const kwikcheckoutAdapter = new KwikCheckoutAdapter(\n addLoggerConfig(config.kwikcheckout),\n );\n adapters.push(kwikcheckoutAdapter);\n logger.info(\"Added KwikCheckout Analytics adapter\");\n }\n\n // Custom adapters\n if (config.customAdapters) {\n adapters.push(...config.customAdapters);\n logger.info(`Added ${config.customAdapters.length} custom adapters`);\n }\n\n if (adapters.length === 0) {\n logger.warn(\"No analytics adapters configured\");\n } else {\n // Initialize the event tracking system\n await initializeEventTracking(adapters);\n logger.info(\"Event tracking initialized with adapters\", {\n adapters: adapters.map((a) => a.name),\n });\n }\n\n logger.info(\"Initialization completed successfully\");\n onInitialized?.();\n } catch (err) {\n const error =\n err instanceof Error\n ? err\n : new Error(\"Unknown initialization error\");\n logger.error(\"Initialization failed\", error);\n onError?.(error);\n }\n };\n\n initializeAnalytics();\n }, [config, onInitialized, onError]);\n\n return (\n <>\n {/* Affiliate Tracker */}\n {config.affiliate?.enabled !== false && (\n <AffiliateTracker\n config={config.affiliate?.config}\n autoCapture={config.affiliate?.autoCapture}\n />\n )}\n\n {/* Shopify Analytics Script - Only render if Shopify config is provided */}\n {config.shopify?.domain && (\n <ShopifyAnalyticsScript domain={config.shopify.domain} />\n )}\n\n {children ? <>{children}</> : null}\n </>\n );\n};\n\nexport default ShopkitAnalytics;\n","\"use client\";\n\nimport { useShopifyCookies } from \"@shopify/hydrogen-react\";\nimport { useEffect, useState } from \"react\";\nimport { EventType, publishEvent } from \"../events\";\n\n// Safe pathname hook that works in different environments\nfunction usePathnameCompat() {\n const [pathname, setPathname] = useState<string>(\"\");\n\n useEffect(() => {\n if (typeof window !== \"undefined\") {\n setPathname(window.location.pathname);\n \n // Listen for navigation changes\n const handleLocationChange = () => {\n setPathname(window.location.pathname);\n };\n\n // Listen for popstate (back/forward navigation)\n window.addEventListener(\"popstate\", handleLocationChange);\n \n // For SPA navigation, we might need to listen to custom events\n // This is a fallback for when Next.js router is not available\n \n return () => {\n window.removeEventListener(\"popstate\", handleLocationChange);\n };\n }\n }, []);\n\n return pathname;\n}\n\n/**\n * Component to initialize Shopify Analytics cookies\n * This component handles the useShopifyCookies hook which must be used in a React component\n */\n\ninterface ShopifyAnalyticsScriptProps {\n domain: string;\n}\n\nexport function ShopifyAnalyticsScript({\n domain,\n}: ShopifyAnalyticsScriptProps) {\n const pathname = usePathnameCompat();\n\n const [sessionValid, setSessionValid] = useState(false);\n\n useShopifyCookies({\n hasUserConsent: true,\n domain: domain,\n });\n\n useEffect(() => {\n // Validate session after cookie initialization\n const validateSession = () => {\n const shopifyY = document.cookie.includes(\"_shopify_y=\");\n const shopifyS = document.cookie.includes(\"_shopify_s=\");\n\n if (shopifyY && shopifyS) {\n setSessionValid(true);\n console.log(\"✅ Shopify Analytics session validated\");\n } else {\n console.warn(\"⚠️ Shopify session cookies missing\");\n }\n };\n\n // Allow time for cookies to be set\n const timer = setTimeout(validateSession, 1000);\n return () => clearTimeout(timer);\n }, []);\n\n // Expose session status for debugging\n useEffect(() => {\n if (typeof window !== \"undefined\") {\n (window as any).__shopifySessionValid = sessionValid;\n }\n }, [sessionValid]);\n\n useEffect(() => {\n const trackPageView = () => {\n publishEvent({\n type: EventType.SHOPIFY_PAGE_VIEW,\n });\n };\n\n const timer = setTimeout(trackPageView, 1500);\n return () => clearTimeout(timer);\n }, [pathname]);\n\n return null; // This component doesn't render anything\n}\n","/**\n * PII Hashing Utilities for Facebook CAPI\n *\n * Provides SHA-256 hashing functions for Personally Identifiable Information\n * before sending to Facebook's Conversion API. All functions normalize input\n * according to Facebook's guidelines.\n *\n * Reference: https://developers.facebook.com/docs/marketing-api/conversions-api/parameters\n */\n\n/**\n * Generic hash function for strings using SHA-256\n * @param value String to hash\n * @param normalize Optional normalization function to apply before hashing\n * @returns Promise resolving to SHA-256 hash or fallback hash\n */\nexport async function hashString(\n value: string | undefined | null,\n normalize?: (v: string) => string\n): Promise<string | undefined> {\n if (!value) {\n return undefined;\n }\n\n try {\n const normalizedValue = normalize ? normalize(value) : value;\n\n // Use Web Crypto API if available (modern browsers and Node.js)\n if (typeof crypto !== \"undefined\" && crypto.subtle) {\n const encoder = new TextEncoder();\n const data = encoder.encode(normalizedValue);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n return hashHex;\n }\n } catch (error) {\n console.error(\"Error hashing with SHA-256:\", error);\n }\n\n // Fallback to simple hash if Web Crypto not available\n return fallbackHash(value);\n}\n\n/**\n * Hash email address\n * Normalized: trimmed and lowercase\n * @param email Email address to hash\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashEmail(\n email: string | undefined | null\n): Promise<string | undefined> {\n return hashString(email, (value) =>\n value.trim().toLowerCase().replace(/\\s+/g, \"\")\n );\n}\n\n/**\n * Hash phone number\n * Normalized: trimmed, lowercase, only digits\n * @param phone Phone number to hash\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashPhone(\n phone: string | undefined | null\n): Promise<string | undefined> {\n return hashString(phone, (value) =>\n value\n .trim()\n .toLowerCase()\n .replace(/\\D/g, \"\") // Remove all non-digits\n );\n}\n\n/**\n * Hash first name\n * Normalized: trimmed and lowercase\n * @param firstName First name to hash\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashFirstName(\n firstName: string | undefined | null\n): Promise<string | undefined> {\n return hashString(firstName, (value) =>\n value.trim().toLowerCase().replace(/\\s+/g, \"\")\n );\n}\n\n/**\n * Hash last name\n * Normalized: trimmed and lowercase\n * @param lastName Last name to hash\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashLastName(\n lastName: string | undefined | null\n): Promise<string | undefined> {\n return hashString(lastName, (value) =>\n value.trim().toLowerCase().replace(/\\s+/g, \"\")\n );\n}\n\n/**\n * Hash IP address\n * Normalized: trimmed\n * @param ip IP address to hash\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashIP(\n ip: string | undefined | null\n): Promise<string | undefined> {\n return hashString(ip, (value) => value.trim());\n}\n\n/**\n * Hash country code\n * Normalized: trimmed and uppercase\n * @param country Country code (US, CA, etc.)\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashCountry(\n country: string | undefined | null\n): Promise<string | undefined> {\n return hashString(country, (value) =>\n value.trim().toUpperCase().replace(/\\s+/g, \"\")\n );\n}\n\n/**\n * Hash state/province code\n * Normalized: trimmed and uppercase\n * @param state State/province code\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashState(\n state: string | undefined | null\n): Promise<string | undefined> {\n return hashString(state, (value) =>\n value.trim().toUpperCase().replace(/\\s+/g, \"\")\n );\n}\n\n/**\n * Hash zip/postal code\n * Normalized: trimmed and lowercase\n * @param zip Zip/postal code\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashZip(\n zip: string | undefined | null\n): Promise<string | undefined> {\n return hashString(zip, (value) =>\n value.trim().toLowerCase().replace(/\\s+/g, \"\")\n );\n}\n\n/**\n * Utility function to hash multiple PII fields at once\n * @param pii Object containing PII fields\n * @returns Promise resolving to object with hashed fields\n */\nexport async function hashPIIFields(pii: {\n email?: string;\n phone?: string;\n firstName?: string;\n lastName?: string;\n country?: string;\n state?: string;\n zip?: string;\n dateOfBirth?: string;\n}): Promise<{\n em?: string;\n ph?: string;\n fn?: string;\n ln?: string;\n country?: string;\n st?: string;\n zp?: string;\n db?: string;\n}> {\n const [em, ph, fn, ln, country, st, zp, db] = await Promise.all([\n pii.email ? hashEmail(pii.email) : undefined,\n pii.phone ? hashPhone(pii.phone) : undefined,\n pii.firstName ? hashFirstName(pii.firstName) : undefined,\n pii.lastName ? hashLastName(pii.lastName) : undefined,\n pii.country ? hashCountry(pii.country) : undefined,\n pii.state ? hashState(pii.state) : undefined,\n pii.zip ? hashZip(pii.zip) : undefined,\n pii.dateOfBirth ? hashString(pii.dateOfBirth?.trim(), (v) => v) : undefined,\n ]);\n\n return {\n ...(em && { em }),\n ...(ph && { ph }),\n ...(fn && { fn }),\n ...(ln && { ln }),\n ...(country && { country }),\n ...(st && { st }),\n ...(zp && { zp }),\n ...(db && { db }),\n };\n}\n\n/**\n * Simple hash fallback for browsers without Web Crypto API\n * This uses a basic string hashing algorithm (not cryptographically secure)\n * @param value String to hash\n * @returns Hex-encoded hash string\n */\nfunction fallbackHash(value: string): string {\n let hash = 0;\n\n if (value.length === 0) {\n return \"0\";\n }\n\n for (let i = 0; i < value.length; i++) {\n const char = value.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32-bit integer\n }\n\n return Math.abs(hash).toString(16).padStart(16, \"0\");\n}\n\n/**\n * Check if crypto API is available in the current environment\n * @returns true if Web Crypto API is available\n */\nexport function isCryptoAvailable(): boolean {\n return typeof crypto !== \"undefined\" && crypto.subtle !== undefined;\n}\n","/**\n * Facebook CAPI Service\n * Core business logic for Facebook Conversion API integration\n * Reusable across multiple projects\n *\n * Handles:\n * - Rate limiting\n * - Event ID generation\n * - fbc/fbp extraction\n * - Event formatting\n * - Retry logic with exponential backoff\n * - Request validation\n * - Timeout handling\n * - PII hashing (IP, email, phone, names)\n */\n\nimport { hashIP } from \"../utils/pii-hashing\";\n\n/**\n * Facebook CAPI Configuration\n */\nexport interface FacebookCAPIConfig {\n pixelId: string;\n accessToken: string;\n baseUrl: string;\n testEventCode?: string;\n}\n\n/**\n * CAPI Event Structure\n */\nexport interface CAPIEvent {\n event_name: string;\n event_time: number;\n event_id: string;\n action_source: \"website\" | \"app\";\n user_data: {\n client_ip_address?: string; // Now hashed in convertToCapiEvent\n client_user_agent?: string;\n fbc?: string;\n fbp?: string;\n // Hashed PII fields (optional)\n em?: string; // Hashed email\n ph?: string; // Hashed phone\n fn?: string; // Hashed first name\n ln?: string; // Hashed last name\n country?: string; // Hashed country code\n st?: string; // Hashed state\n zp?: string; // Hashed zip code\n db?: string; // Hashed date of birth\n external_id?: string; // Customer or order ID\n };\n custom_data: Record<string, any>;\n}\n\n/**\n * Rate Limiter - tracks requests per IP address\n * In-memory implementation (can be extended with Redis)\n */\nexport class RateLimiter {\n private store = new Map<string, { count: number; resetTime: number }>();\n private readonly limit: number;\n private readonly window: number;\n\n constructor(requestsPerMinute: number = 100) {\n this.limit = requestsPerMinute;\n this.window = 60 * 1000; // 1 minute\n }\n\n check(ip: string): { allowed: boolean; remaining: number } {\n const now = Date.now();\n let entry = this.store.get(ip);\n\n // Clean up expired entries\n if (entry && entry.resetTime < now) {\n this.store.delete(ip);\n entry = undefined;\n }\n\n if (!entry) {\n entry = { count: 0, resetTime: now + this.window };\n this.store.set(ip, entry);\n }\n\n const allowed = entry.count < this.limit;\n entry.count++;\n\n return {\n allowed,\n remaining: Math.max(0, this.limit - entry.count),\n };\n }\n}\n\n/**\n * Facebook CAPI Service\n * Core business logic for CAPI integration\n */\nexport class FacebookCAPIService {\n private rateLimiter = new RateLimiter(100); // 100 requests per minute per IP\n private readonly maxRetries = 3;\n private readonly baseDelay = 1000; // 1 second\n private readonly timeout = 30000; // 30 seconds\n private readonly debug = false; // Override in consuming projects if needed\n\n /**\n * Check if request is within rate limits\n */\n checkRateLimit(clientIp: string): { allowed: boolean; remaining: number } {\n return this.rateLimiter.check(clientIp);\n }\n\n /**\n * Generate a unique event ID for deduplication\n */\n generateEventId(eventName: string): string {\n const timestamp = Date.now();\n const randomString = Math.random().toString(36).substring(2, 8);\n return `${timestamp}_${randomString}_${eventName}`;\n }\n\n /**\n * Extract fbc cookie from request headers\n */\n extractFbcFromRequest(request: Request): string | undefined {\n const cookieHeader = request.headers.get(\"cookie\");\n if (!cookieHeader) return undefined;\n\n const cookies = cookieHeader.split(\";\");\n for (const cookie of cookies) {\n const [name, value] = cookie.trim().split(\"=\");\n if (name === \"_fbc\") {\n return value;\n }\n }\n\n return undefined;\n }\n\n /**\n * Get client IP address from request headers\n */\n getClientIpAddress(request: Request): string | undefined {\n const forwarded = request.headers.get(\"x-forwarded-for\");\n const realIp = request.headers.get(\"x-real-ip\");\n const cfConnectingIp = request.headers.get(\"cf-connecting-ip\");\n\n return forwarded?.split(\",\")[0] || realIp || cfConnectingIp || undefined;\n }\n\n /**\n * Convert event to Facebook CAPI format with optional PII hashing\n * Note: This method is now async to support SHA-256 IP hashing\n */\n async convertToCapiEvent(\n eventName: string,\n eventId: string,\n timestamp: number | undefined,\n enhancedParams: any,\n userInfo: any,\n ): Promise<CAPIEvent> {\n // Facebook CAPI expects Unix timestamp (seconds since epoch)\n const eventTime = timestamp\n ? Math.floor(timestamp / 1000)\n : Math.floor(Date.now() / 1000);\n\n // Hash IP address if provided (security best practice)\n let hashedIp: string | undefined;\n if (userInfo?.clientIpAddress) {\n try {\n hashedIp = await hashIP(userInfo.clientIpAddress);\n } catch (error) {\n console.error(\"[Facebook CAPI] Error hashing IP:\", error);\n // Fall back to unhashed if hashing fails\n hashedIp = userInfo.clientIpAddress;\n }\n }\n\n if (this.debug) {\n console.log(\"[Facebook CAPI] Event Conversion\", {\n eventName,\n eventId,\n eventTime,\n timestamp_input: timestamp,\n fbp: !!userInfo?.fbp,\n fbc: !!userInfo?.fbc,\n ip_hashed: !!hashedIp,\n pii_fields: {\n em: !!userInfo?.em,\n ph: !!userInfo?.ph,\n fn: !!userInfo?.fn,\n ln: !!userInfo?.ln,\n },\n });\n }\n\n const capiEvent: CAPIEvent = {\n event_name: eventName,\n event_time: eventTime,\n event_id: eventId,\n action_source: \"website\",\n user_data: {\n client_ip_address: hashedIp,\n client_user_agent: userInfo?.clientUserAgent,\n fbc: userInfo?.fbc,\n fbp: userInfo?.fbp,\n },\n custom_data: enhancedParams,\n };\n\n // Add optional hashed PII fields if provided\n if (userInfo?.em) {\n capiEvent.user_data.em = userInfo.em;\n }\n if (userInfo?.ph) {\n capiEvent.user_data.ph = userInfo.ph;\n }\n if (userInfo?.fn) {\n capiEvent.user_data.fn = userInfo.fn;\n }\n if (userInfo?.ln) {\n capiEvent.user_data.ln = userInfo.ln;\n }\n if (userInfo?.country) {\n capiEvent.user_data.country = userInfo.country;\n }\n if (userInfo?.st) {\n capiEvent.user_data.st = userInfo.st;\n }\n if (userInfo?.zp) {\n capiEvent.user_data.zp = userInfo.zp;\n }\n if (userInfo?.db) {\n capiEvent.user_data.db = userInfo.db;\n }\n if (userInfo?.external_id) {\n capiEvent.user_data.external_id = userInfo.external_id;\n }\n\n return capiEvent;\n }\n\n /**\n * Send event to Facebook CAPI with retry logic\n */\n async sendToFacebook(\n config: FacebookCAPIConfig,\n capiEvent: CAPIEvent,\n ): Promise<{\n success: boolean;\n data?: any;\n error?: string;\n pixelId: string;\n }> {\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const payload = {\n data: [capiEvent],\n test_event_code: config.testEventCode,\n };\n\n if (this.debug) {\n console.log(\"[Facebook CAPI] Sending to Facebook\", {\n pixelId: config.pixelId,\n eventId: capiEvent.event_id,\n eventName: capiEvent.event_name,\n attempt: attempt + 1,\n });\n }\n\n const url = `${config.baseUrl}/${config.pixelId}/events?access_token=${config.accessToken}`;\n\n // Create timeout abort controller\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n // Retry on 5xx errors (server errors) and 429 (rate limit)\n if (\n (response.status >= 500 || response.status === 429) &&\n attempt < this.maxRetries\n ) {\n const delay = this.baseDelay * Math.pow(2, attempt);\n if (this.debug) {\n console.log(`[Facebook CAPI] Retrying in ${delay}ms`, {\n pixelId: config.pixelId,\n status: response.status,\n });\n }\n await new Promise((resolve) => setTimeout(resolve, delay));\n continue; // Retry\n }\n\n console.error(\n `Facebook CAPI Error for pixel ${config.pixelId} (attempt ${attempt + 1}/${this.maxRetries + 1}):`,\n { status: response.status },\n );\n return {\n success: false,\n error: `Facebook CAPI request failed: ${response.status}`,\n pixelId: config.pixelId,\n };\n }\n\n const result = await response.json();\n if (this.debug) {\n console.log(\n `Facebook CAPI: Events sent successfully to pixel ${config.pixelId}`,\n {\n events_received: result.events_received,\n },\n );\n }\n\n return {\n success: true,\n data: result,\n pixelId: config.pixelId,\n };\n } finally {\n clearTimeout(timeoutId);\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n\n // Retry on network errors and timeouts\n if (attempt < this.maxRetries) {\n const delay = this.baseDelay * Math.pow(2, attempt);\n if (this.debug) {\n console.log(`[Facebook CAPI] Retrying in ${delay}ms after error`, {\n pixelId: config.pixelId,\n error: errorMessage,\n });\n }\n await new Promise((resolve) => setTimeout(resolve, delay));\n continue; // Retry\n }\n\n console.error(\n `Facebook CAPI Network Error for pixel ${config.pixelId} (attempt ${attempt + 1}/${this.maxRetries + 1}):`,\n { error: errorMessage },\n );\n return {\n success: false,\n error: `Network error: ${errorMessage}`,\n pixelId: config.pixelId,\n };\n }\n }\n\n return {\n success: false,\n error: \"Failed after all retry attempts\",\n pixelId: config.pixelId,\n };\n }\n\n /**\n * Validate request body\n */\n validateRequestBody(\n eventName: string,\n enhancedParams: any,\n bodySize: number,\n ): { valid: boolean; error?: string } {\n // Validate required fields\n if (!eventName || !enhancedParams) {\n return {\n valid: false,\n error: \"eventName and enhancedParams are required\",\n };\n }\n\n // Validate body size (max 1MB)\n if (bodySize > 1024 * 1024) {\n return {\n valid: false,\n error: \"Request body too large (max 1MB)\",\n };\n }\n\n // Validate eventName format (alphanumeric and underscore only)\n if (!/^[a-zA-Z0-9_]+$/.test(eventName)) {\n return {\n valid: false,\n error:\n \"eventName must contain only alphanumeric characters and underscores\",\n };\n }\n\n return { valid: true };\n }\n}\n\n/**\n * Singleton instance of the service\n */\nexport const facebookCAPIService = new FacebookCAPIService();\n"],"mappings":"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","names":["useEffect","useEffect","logger"]}
1
+ {"version":3,"sources":["../src/ShopkitAnalytics.tsx","../src/shopify/ShopifyAnalyticsScript.tsx","../src/utils/pii-hashing.ts","../src/services/facebook-capi.service.ts"],"sourcesContent":["\"use client\";\n\n/**\n * ShopkitAnalytics Component\n *\n * Main analytics provider component that initializes and manages\n * all configured analytics adapters.\n *\n * @module @shopkit/analytics\n */\n\nimport React, { useEffect } from \"react\";\nimport { initializeEventTracking } from \"./events/init\";\nimport { AffiliateTracker } from \"./affiliate\";\nimport { createLogger, type LoggerConfig } from \"./logger\";\nimport {\n GoogleAdapter,\n MultiPixelAdapter,\n MoengageAdapter,\n PostHogAdapter,\n ShopifyAdapter,\n} from \"./adapters\";\nimport type {\n GoogleAdapterConfig,\n MultiPixelAdapterConfig,\n MoengageAdapterConfig,\n PostHogAdapterConfig,\n ShopifyAdapterConfig,\n} from \"./adapters\";\nimport type { TrackingAdapter } from \"./events/subscriber\";\nimport type { AffiliateConfig } from \"./affiliate/types\";\nimport { ShopifyAnalyticsScript } from \"./shopify/ShopifyAnalyticsScript\";\n\n/**\n * Configuration for ShopkitAnalytics component\n *\n * @example\n * ```typescript\n * const config: ShopkitAnalyticsConfig = {\n * googleAnalytics: { measurementId: 'G-XXXXXX' },\n * facebookPixel: { pixelId: '123456789' },\n * posthog: { apiKey: 'phc_xxx', apiHost: 'https://app.posthog.com' },\n * logger: { enabled: true, level: 'info' },\n * };\n * ```\n */\nexport interface ShopkitAnalyticsConfig {\n // Analytics Adapters\n googleAnalytics?: GoogleAdapterConfig;\n facebookMultiPixel?: MultiPixelAdapterConfig;\n moengage?: MoengageAdapterConfig;\n posthog?: PostHogAdapterConfig;\n shopify?: ShopifyAdapterConfig;\n customAdapters?: TrackingAdapter[];\n\n // Affiliate Tracking\n affiliate?: {\n enabled?: boolean;\n config?: Partial<AffiliateConfig>;\n autoCapture?: boolean;\n };\n\n // Logger Settings\n logger?: LoggerConfig;\n\n // General Settings (deprecated - use logger.enabled instead)\n enableDebugLogs?: boolean;\n autoInitialize?: boolean;\n}\n\n/**\n * Props for ShopkitAnalytics component\n */\nexport interface ShopkitAnalyticsProps {\n /** Analytics configuration object */\n config: ShopkitAnalyticsConfig;\n /** Optional children to render */\n children?: React.ReactNode;\n /** Callback when analytics initialization completes */\n onInitialized?: () => void;\n /** Callback when an error occurs during initialization */\n onError?: (error: Error) => void;\n}\n\n/**\n * ShopkitAnalytics Component\n *\n * The main analytics provider that initializes all configured tracking adapters\n * and sets up event publishing infrastructure.\n *\n * Place this component in your app's root layout to enable analytics tracking\n * throughout your application.\n *\n * @param props - Component props\n * @returns React component with analytics initialization and affiliate tracking\n *\n * @example\n * ```typescript\n * // In your root layout\n * import { ShopkitAnalytics } from '@shopkit/analytics';\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html>\n * <body>\n * <ShopkitAnalytics\n * config={{\n * googleAnalytics: { measurementId: 'G-XXXXXX' },\n * facebookPixel: { pixelId: '123456789' },\n * }}\n * onInitialized={() => console.log('Analytics ready')}\n * onError={(err) => console.error('Analytics error:', err)}\n * >\n * {children}\n * </ShopkitAnalytics>\n * </body>\n * </html>\n * );\n * }\n * ```\n */\nconst ShopkitAnalytics: React.FC<ShopkitAnalyticsProps> = ({\n config,\n children,\n onInitialized,\n onError,\n}) => {\n useEffect(() => {\n const initializeAnalytics = async () => {\n if (config.autoInitialize === false) return;\n\n // Create logger instance\n const loggerConfig: LoggerConfig = {\n enabled: config.logger?.enabled ?? config.enableDebugLogs ?? true,\n level: config.logger?.level ?? \"info\",\n name: \"@shopkit/analytics\",\n prettyPrint: config.logger?.prettyPrint ?? false,\n };\n\n const logger = createLogger(loggerConfig);\n\n try {\n logger.info(\"Starting initialization...\");\n\n const adapters: TrackingAdapter[] = [];\n\n // Helper function to add logger config to adapter config\n const addLoggerConfig = (adapterConfig: any) => ({\n ...adapterConfig,\n enableDebugLogs: loggerConfig.enabled,\n logLevel: loggerConfig.level,\n });\n\n // Google Analytics 4\n if (config.googleAnalytics) {\n const gaAdapter = new GoogleAdapter(\n addLoggerConfig(config.googleAnalytics),\n );\n adapters.push(gaAdapter);\n logger.info(\"Added Google Analytics adapter\");\n }\n\n // Facebook Multi-Pixel\n if (config.facebookMultiPixel) {\n const multiPixelAdapter = new MultiPixelAdapter(\n addLoggerConfig(config.facebookMultiPixel),\n );\n adapters.push(multiPixelAdapter);\n logger.info(\n `Added Facebook Multi-Pixel adapter with ${config.facebookMultiPixel.pixels.length} pixels`,\n );\n }\n\n // MoEngage\n if (config.moengage) {\n const moengageAdapter = new MoengageAdapter(\n addLoggerConfig(config.moengage),\n );\n adapters.push(moengageAdapter);\n logger.info(\"Added MoEngage adapter\");\n }\n\n // PostHog\n if (config.posthog) {\n const posthogAdapter = new PostHogAdapter(\n addLoggerConfig(config.posthog),\n );\n adapters.push(posthogAdapter);\n logger.info(\"Added PostHog adapter\");\n }\n\n // Shopify Analytics\n if (config.shopify) {\n const shopifyAdapter = new ShopifyAdapter(\n addLoggerConfig(config.shopify),\n );\n adapters.push(shopifyAdapter);\n logger.info(\"Added Shopify Analytics adapter\");\n }\n\n // Custom adapters\n if (config.customAdapters) {\n adapters.push(...config.customAdapters);\n logger.info(`Added ${config.customAdapters.length} custom adapters`);\n }\n\n if (adapters.length === 0) {\n logger.warn(\"No analytics adapters configured\");\n } else {\n // Initialize the event tracking system\n await initializeEventTracking(adapters);\n logger.info(\"Event tracking initialized with adapters\", {\n adapters: adapters.map((a) => a.name),\n });\n }\n\n logger.info(\"Initialization completed successfully\");\n onInitialized?.();\n } catch (err) {\n const error =\n err instanceof Error\n ? err\n : new Error(\"Unknown initialization error\");\n logger.error(\"Initialization failed\", error);\n onError?.(error);\n }\n };\n\n initializeAnalytics();\n }, [config, onInitialized, onError]);\n\n return (\n <>\n {/* Affiliate Tracker */}\n {config.affiliate?.enabled !== false && (\n <AffiliateTracker\n config={config.affiliate?.config}\n autoCapture={config.affiliate?.autoCapture}\n />\n )}\n\n {/* Shopify Analytics Script - Only render if Shopify config is provided */}\n {config.shopify?.domain && (\n <ShopifyAnalyticsScript domain={config.shopify.domain} />\n )}\n\n {children ? <>{children}</> : null}\n </>\n );\n};\n\nexport default ShopkitAnalytics;\n","\"use client\";\n\nimport { useShopifyCookies } from \"@shopify/hydrogen-react\";\nimport { useEffect, useState } from \"react\";\nimport { EventType, publishEvent } from \"../events\";\n\n// Safe pathname hook that works in different environments\nfunction usePathnameCompat() {\n const [pathname, setPathname] = useState<string>(\"\");\n\n useEffect(() => {\n if (typeof window !== \"undefined\") {\n setPathname(window.location.pathname);\n \n // Listen for navigation changes\n const handleLocationChange = () => {\n setPathname(window.location.pathname);\n };\n\n // Listen for popstate (back/forward navigation)\n window.addEventListener(\"popstate\", handleLocationChange);\n \n // For SPA navigation, we might need to listen to custom events\n // This is a fallback for when Next.js router is not available\n \n return () => {\n window.removeEventListener(\"popstate\", handleLocationChange);\n };\n }\n }, []);\n\n return pathname;\n}\n\n/**\n * Component to initialize Shopify Analytics cookies\n * This component handles the useShopifyCookies hook which must be used in a React component\n */\n\ninterface ShopifyAnalyticsScriptProps {\n domain: string;\n}\n\nexport function ShopifyAnalyticsScript({\n domain,\n}: ShopifyAnalyticsScriptProps) {\n const pathname = usePathnameCompat();\n\n const [sessionValid, setSessionValid] = useState(false);\n\n useShopifyCookies({\n hasUserConsent: true,\n domain: domain,\n });\n\n useEffect(() => {\n // Validate session after cookie initialization\n const validateSession = () => {\n const shopifyY = document.cookie.includes(\"_shopify_y=\");\n const shopifyS = document.cookie.includes(\"_shopify_s=\");\n\n if (shopifyY && shopifyS) {\n setSessionValid(true);\n console.log(\"✅ Shopify Analytics session validated\");\n } else {\n console.warn(\"⚠️ Shopify session cookies missing\");\n }\n };\n\n // Allow time for cookies to be set\n const timer = setTimeout(validateSession, 1000);\n return () => clearTimeout(timer);\n }, []);\n\n // Expose session status for debugging\n useEffect(() => {\n if (typeof window !== \"undefined\") {\n (window as any).__shopifySessionValid = sessionValid;\n }\n }, [sessionValid]);\n\n useEffect(() => {\n const trackPageView = () => {\n publishEvent({\n type: EventType.SHOPIFY_PAGE_VIEW,\n });\n };\n\n const timer = setTimeout(trackPageView, 1500);\n return () => clearTimeout(timer);\n }, [pathname]);\n\n return null; // This component doesn't render anything\n}\n","/**\n * PII Hashing Utilities for Facebook CAPI\n *\n * Provides SHA-256 hashing functions for Personally Identifiable Information\n * before sending to Facebook's Conversion API. All functions normalize input\n * according to Facebook's guidelines.\n *\n * Reference: https://developers.facebook.com/docs/marketing-api/conversions-api/parameters\n */\n\n/**\n * Generic hash function for strings using SHA-256\n * @param value String to hash\n * @param normalize Optional normalization function to apply before hashing\n * @returns Promise resolving to SHA-256 hash or fallback hash\n */\nexport async function hashString(\n value: string | undefined | null,\n normalize?: (v: string) => string\n): Promise<string | undefined> {\n if (!value) {\n return undefined;\n }\n\n try {\n const normalizedValue = normalize ? normalize(value) : value;\n\n // Use Web Crypto API if available (modern browsers and Node.js)\n if (typeof crypto !== \"undefined\" && crypto.subtle) {\n const encoder = new TextEncoder();\n const data = encoder.encode(normalizedValue);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n return hashHex;\n }\n } catch (error) {\n console.error(\"Error hashing with SHA-256:\", error);\n }\n\n // Fallback to simple hash if Web Crypto not available\n return fallbackHash(value);\n}\n\n/**\n * Hash email address\n * Normalized: trimmed and lowercase\n * @param email Email address to hash\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashEmail(\n email: string | undefined | null\n): Promise<string | undefined> {\n return hashString(email, (value) =>\n value.trim().toLowerCase().replace(/\\s+/g, \"\")\n );\n}\n\n/**\n * Hash phone number\n * Normalized: trimmed, lowercase, only digits\n * @param phone Phone number to hash\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashPhone(\n phone: string | undefined | null\n): Promise<string | undefined> {\n return hashString(phone, (value) =>\n value\n .trim()\n .toLowerCase()\n .replace(/\\D/g, \"\") // Remove all non-digits\n );\n}\n\n/**\n * Hash first name\n * Normalized: trimmed and lowercase\n * @param firstName First name to hash\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashFirstName(\n firstName: string | undefined | null\n): Promise<string | undefined> {\n return hashString(firstName, (value) =>\n value.trim().toLowerCase().replace(/\\s+/g, \"\")\n );\n}\n\n/**\n * Hash last name\n * Normalized: trimmed and lowercase\n * @param lastName Last name to hash\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashLastName(\n lastName: string | undefined | null\n): Promise<string | undefined> {\n return hashString(lastName, (value) =>\n value.trim().toLowerCase().replace(/\\s+/g, \"\")\n );\n}\n\n/**\n * Hash IP address\n * Normalized: trimmed\n * @param ip IP address to hash\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashIP(\n ip: string | undefined | null\n): Promise<string | undefined> {\n return hashString(ip, (value) => value.trim());\n}\n\n/**\n * Hash country code\n * Normalized: trimmed and uppercase\n * @param country Country code (US, CA, etc.)\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashCountry(\n country: string | undefined | null\n): Promise<string | undefined> {\n return hashString(country, (value) =>\n value.trim().toUpperCase().replace(/\\s+/g, \"\")\n );\n}\n\n/**\n * Hash state/province code\n * Normalized: trimmed and uppercase\n * @param state State/province code\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashState(\n state: string | undefined | null\n): Promise<string | undefined> {\n return hashString(state, (value) =>\n value.trim().toUpperCase().replace(/\\s+/g, \"\")\n );\n}\n\n/**\n * Hash zip/postal code\n * Normalized: trimmed and lowercase\n * @param zip Zip/postal code\n * @returns Promise resolving to SHA-256 hash\n */\nexport async function hashZip(\n zip: string | undefined | null\n): Promise<string | undefined> {\n return hashString(zip, (value) =>\n value.trim().toLowerCase().replace(/\\s+/g, \"\")\n );\n}\n\n/**\n * Utility function to hash multiple PII fields at once\n * @param pii Object containing PII fields\n * @returns Promise resolving to object with hashed fields\n */\nexport async function hashPIIFields(pii: {\n email?: string;\n phone?: string;\n firstName?: string;\n lastName?: string;\n country?: string;\n state?: string;\n zip?: string;\n dateOfBirth?: string;\n}): Promise<{\n em?: string;\n ph?: string;\n fn?: string;\n ln?: string;\n country?: string;\n st?: string;\n zp?: string;\n db?: string;\n}> {\n const [em, ph, fn, ln, country, st, zp, db] = await Promise.all([\n pii.email ? hashEmail(pii.email) : undefined,\n pii.phone ? hashPhone(pii.phone) : undefined,\n pii.firstName ? hashFirstName(pii.firstName) : undefined,\n pii.lastName ? hashLastName(pii.lastName) : undefined,\n pii.country ? hashCountry(pii.country) : undefined,\n pii.state ? hashState(pii.state) : undefined,\n pii.zip ? hashZip(pii.zip) : undefined,\n pii.dateOfBirth ? hashString(pii.dateOfBirth?.trim(), (v) => v) : undefined,\n ]);\n\n return {\n ...(em && { em }),\n ...(ph && { ph }),\n ...(fn && { fn }),\n ...(ln && { ln }),\n ...(country && { country }),\n ...(st && { st }),\n ...(zp && { zp }),\n ...(db && { db }),\n };\n}\n\n/**\n * Simple hash fallback for browsers without Web Crypto API\n * This uses a basic string hashing algorithm (not cryptographically secure)\n * @param value String to hash\n * @returns Hex-encoded hash string\n */\nfunction fallbackHash(value: string): string {\n let hash = 0;\n\n if (value.length === 0) {\n return \"0\";\n }\n\n for (let i = 0; i < value.length; i++) {\n const char = value.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32-bit integer\n }\n\n return Math.abs(hash).toString(16).padStart(16, \"0\");\n}\n\n/**\n * Check if crypto API is available in the current environment\n * @returns true if Web Crypto API is available\n */\nexport function isCryptoAvailable(): boolean {\n return typeof crypto !== \"undefined\" && crypto.subtle !== undefined;\n}\n","/**\n * Facebook CAPI Service\n * Core business logic for Facebook Conversion API integration\n * Reusable across multiple projects\n *\n * Handles:\n * - Rate limiting\n * - Event ID generation\n * - fbc/fbp extraction\n * - Event formatting\n * - Retry logic with exponential backoff\n * - Request validation\n * - Timeout handling\n * - PII hashing (IP, email, phone, names)\n */\n\nimport { hashIP } from \"../utils/pii-hashing\";\n\n/**\n * Facebook CAPI Configuration\n */\nexport interface FacebookCAPIConfig {\n pixelId: string;\n accessToken: string;\n baseUrl: string;\n testEventCode?: string;\n}\n\n/**\n * CAPI Event Structure\n */\nexport interface CAPIEvent {\n event_name: string;\n event_time: number;\n event_id: string;\n action_source: \"website\" | \"app\";\n user_data: {\n client_ip_address?: string; // Now hashed in convertToCapiEvent\n client_user_agent?: string;\n fbc?: string;\n fbp?: string;\n // Hashed PII fields (optional)\n em?: string; // Hashed email\n ph?: string; // Hashed phone\n fn?: string; // Hashed first name\n ln?: string; // Hashed last name\n country?: string; // Hashed country code\n st?: string; // Hashed state\n zp?: string; // Hashed zip code\n db?: string; // Hashed date of birth\n external_id?: string; // Customer or order ID\n };\n custom_data: Record<string, any>;\n}\n\n/**\n * Rate Limiter - tracks requests per IP address\n * In-memory implementation (can be extended with Redis)\n */\nexport class RateLimiter {\n private store = new Map<string, { count: number; resetTime: number }>();\n private readonly limit: number;\n private readonly window: number;\n\n constructor(requestsPerMinute: number = 100) {\n this.limit = requestsPerMinute;\n this.window = 60 * 1000; // 1 minute\n }\n\n check(ip: string): { allowed: boolean; remaining: number } {\n const now = Date.now();\n let entry = this.store.get(ip);\n\n // Clean up expired entries\n if (entry && entry.resetTime < now) {\n this.store.delete(ip);\n entry = undefined;\n }\n\n if (!entry) {\n entry = { count: 0, resetTime: now + this.window };\n this.store.set(ip, entry);\n }\n\n const allowed = entry.count < this.limit;\n entry.count++;\n\n return {\n allowed,\n remaining: Math.max(0, this.limit - entry.count),\n };\n }\n}\n\n/**\n * Facebook CAPI Service\n * Core business logic for CAPI integration\n */\nexport class FacebookCAPIService {\n private rateLimiter = new RateLimiter(100); // 100 requests per minute per IP\n private readonly maxRetries = 3;\n private readonly baseDelay = 1000; // 1 second\n private readonly timeout = 30000; // 30 seconds\n private readonly debug = false; // Override in consuming projects if needed\n\n /**\n * Check if request is within rate limits\n */\n checkRateLimit(clientIp: string): { allowed: boolean; remaining: number } {\n return this.rateLimiter.check(clientIp);\n }\n\n /**\n * Generate a unique event ID for deduplication\n */\n generateEventId(eventName: string): string {\n const timestamp = Date.now();\n const randomString = Math.random().toString(36).substring(2, 8);\n return `${timestamp}_${randomString}_${eventName}`;\n }\n\n /**\n * Extract fbc cookie from request headers\n */\n extractFbcFromRequest(request: Request): string | undefined {\n const cookieHeader = request.headers.get(\"cookie\");\n if (!cookieHeader) return undefined;\n\n const cookies = cookieHeader.split(\";\");\n for (const cookie of cookies) {\n const [name, value] = cookie.trim().split(\"=\");\n if (name === \"_fbc\") {\n return value;\n }\n }\n\n return undefined;\n }\n\n /**\n * Get client IP address from request headers\n */\n getClientIpAddress(request: Request): string | undefined {\n const forwarded = request.headers.get(\"x-forwarded-for\");\n const realIp = request.headers.get(\"x-real-ip\");\n const cfConnectingIp = request.headers.get(\"cf-connecting-ip\");\n\n return forwarded?.split(\",\")[0] || realIp || cfConnectingIp || undefined;\n }\n\n /**\n * Convert event to Facebook CAPI format with optional PII hashing\n * Note: This method is now async to support SHA-256 IP hashing\n */\n async convertToCapiEvent(\n eventName: string,\n eventId: string,\n timestamp: number | undefined,\n enhancedParams: any,\n userInfo: any,\n ): Promise<CAPIEvent> {\n // Facebook CAPI expects Unix timestamp (seconds since epoch)\n const eventTime = timestamp\n ? Math.floor(timestamp / 1000)\n : Math.floor(Date.now() / 1000);\n\n // Hash IP address if provided (security best practice)\n let hashedIp: string | undefined;\n if (userInfo?.clientIpAddress) {\n try {\n hashedIp = await hashIP(userInfo.clientIpAddress);\n } catch (error) {\n console.error(\"[Facebook CAPI] Error hashing IP:\", error);\n // Fall back to unhashed if hashing fails\n hashedIp = userInfo.clientIpAddress;\n }\n }\n\n if (this.debug) {\n console.log(\"[Facebook CAPI] Event Conversion\", {\n eventName,\n eventId,\n eventTime,\n timestamp_input: timestamp,\n fbp: !!userInfo?.fbp,\n fbc: !!userInfo?.fbc,\n ip_hashed: !!hashedIp,\n pii_fields: {\n em: !!userInfo?.em,\n ph: !!userInfo?.ph,\n fn: !!userInfo?.fn,\n ln: !!userInfo?.ln,\n },\n });\n }\n\n const capiEvent: CAPIEvent = {\n event_name: eventName,\n event_time: eventTime,\n event_id: eventId,\n action_source: \"website\",\n user_data: {\n client_ip_address: hashedIp,\n client_user_agent: userInfo?.clientUserAgent,\n fbc: userInfo?.fbc,\n fbp: userInfo?.fbp,\n },\n custom_data: enhancedParams,\n };\n\n // Add optional hashed PII fields if provided\n if (userInfo?.em) {\n capiEvent.user_data.em = userInfo.em;\n }\n if (userInfo?.ph) {\n capiEvent.user_data.ph = userInfo.ph;\n }\n if (userInfo?.fn) {\n capiEvent.user_data.fn = userInfo.fn;\n }\n if (userInfo?.ln) {\n capiEvent.user_data.ln = userInfo.ln;\n }\n if (userInfo?.country) {\n capiEvent.user_data.country = userInfo.country;\n }\n if (userInfo?.st) {\n capiEvent.user_data.st = userInfo.st;\n }\n if (userInfo?.zp) {\n capiEvent.user_data.zp = userInfo.zp;\n }\n if (userInfo?.db) {\n capiEvent.user_data.db = userInfo.db;\n }\n if (userInfo?.external_id) {\n capiEvent.user_data.external_id = userInfo.external_id;\n }\n\n return capiEvent;\n }\n\n /**\n * Send event to Facebook CAPI with retry logic\n */\n async sendToFacebook(\n config: FacebookCAPIConfig,\n capiEvent: CAPIEvent,\n ): Promise<{\n success: boolean;\n data?: any;\n error?: string;\n pixelId: string;\n }> {\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const payload = {\n data: [capiEvent],\n test_event_code: config.testEventCode,\n };\n\n if (this.debug) {\n console.log(\"[Facebook CAPI] Sending to Facebook\", {\n pixelId: config.pixelId,\n eventId: capiEvent.event_id,\n eventName: capiEvent.event_name,\n attempt: attempt + 1,\n });\n }\n\n const url = `${config.baseUrl}/${config.pixelId}/events?access_token=${config.accessToken}`;\n\n // Create timeout abort controller\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n // Retry on 5xx errors (server errors) and 429 (rate limit)\n if (\n (response.status >= 500 || response.status === 429) &&\n attempt < this.maxRetries\n ) {\n const delay = this.baseDelay * Math.pow(2, attempt);\n if (this.debug) {\n console.log(`[Facebook CAPI] Retrying in ${delay}ms`, {\n pixelId: config.pixelId,\n status: response.status,\n });\n }\n await new Promise((resolve) => setTimeout(resolve, delay));\n continue; // Retry\n }\n\n console.error(\n `Facebook CAPI Error for pixel ${config.pixelId} (attempt ${attempt + 1}/${this.maxRetries + 1}):`,\n { status: response.status },\n );\n return {\n success: false,\n error: `Facebook CAPI request failed: ${response.status}`,\n pixelId: config.pixelId,\n };\n }\n\n const result = await response.json();\n if (this.debug) {\n console.log(\n `Facebook CAPI: Events sent successfully to pixel ${config.pixelId}`,\n {\n events_received: result.events_received,\n },\n );\n }\n\n return {\n success: true,\n data: result,\n pixelId: config.pixelId,\n };\n } finally {\n clearTimeout(timeoutId);\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n\n // Retry on network errors and timeouts\n if (attempt < this.maxRetries) {\n const delay = this.baseDelay * Math.pow(2, attempt);\n if (this.debug) {\n console.log(`[Facebook CAPI] Retrying in ${delay}ms after error`, {\n pixelId: config.pixelId,\n error: errorMessage,\n });\n }\n await new Promise((resolve) => setTimeout(resolve, delay));\n continue; // Retry\n }\n\n console.error(\n `Facebook CAPI Network Error for pixel ${config.pixelId} (attempt ${attempt + 1}/${this.maxRetries + 1}):`,\n { error: errorMessage },\n );\n return {\n success: false,\n error: `Network error: ${errorMessage}`,\n pixelId: config.pixelId,\n };\n }\n }\n\n return {\n success: false,\n error: \"Failed after all retry attempts\",\n pixelId: config.pixelId,\n };\n }\n\n /**\n * Validate request body\n */\n validateRequestBody(\n eventName: string,\n enhancedParams: any,\n bodySize: number,\n ): { valid: boolean; error?: string } {\n // Validate required fields\n if (!eventName || !enhancedParams) {\n return {\n valid: false,\n error: \"eventName and enhancedParams are required\",\n };\n }\n\n // Validate body size (max 1MB)\n if (bodySize > 1024 * 1024) {\n return {\n valid: false,\n error: \"Request body too large (max 1MB)\",\n };\n }\n\n // Validate eventName format (alphanumeric and underscore only)\n if (!/^[a-zA-Z0-9_]+$/.test(eventName)) {\n return {\n valid: false,\n error:\n \"eventName must contain only alphanumeric characters and underscores\",\n };\n }\n\n return { valid: true };\n }\n}\n\n/**\n * Singleton instance of the service\n */\nexport const facebookCAPIService = new FacebookCAPIService();\n"],"mappings":"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","names":["useEffect","useEffect","logger"]}
package/dist/types.d.mts CHANGED
@@ -23,26 +23,6 @@ declare enum EventType {
23
23
  USER_SIGNUP = "user_signup",
24
24
  /** User login tracking */
25
25
  USER_LOGIN = "user_login",
26
- /** Checkout initiation */
27
- STARTED_CHECKOUT_GK = "started_checkout_gk",
28
- /** Contact information collection */
29
- MOBILE_ADDED_GK = "mobile_added_gk",
30
- /** Address management events */
31
- PIN_CODE_ADDED_GK = "pin_code_added_gk",
32
- ADDRESS_ADDED_GK = "address_added_gk",
33
- ADDRESS_SELECTED_GK = "address_selected_gk",
34
- ADDRESS_COMPLETED_GK = "address_completed_gk",
35
- /** Payment flow events */
36
- PAYMENT_METHOD_SELECTED_GK = "payment_method_selected_gk",
37
- PAYMENT_COMPLETED_GK = "payment_completed_gk",
38
- /** Order completion events */
39
- ORDER_SUCCESS = "order_success",
40
- ORDER_COMPLETED = "order_completed",
41
- /** Product interaction tracking through KwikPass */
42
- PRODUCT_VIEW_KP = "product_view_kp",
43
- COLLECTION_VIEW_KP = "collection_view_kp",
44
- /** Page navigation tracking through KwikPass */
45
- PAGE_VIEW_KP = "page_view_kp",
46
26
  /** Shopify analytics integration - Do Not Remove */
47
27
  SHOPIFY_PAGE_VIEW = "shopify_page_view",
48
28
  /** Generic custom event for any tracking needs */
@@ -242,113 +222,6 @@ interface ICustomEvent extends BaseEvent {
242
222
  interface ISpecificEvent extends BaseEvent {
243
223
  type: EventType.SPECIFIC;
244
224
  }
245
- /**
246
- * Started checkout GK event - Tracks when user initiates GoKwik checkout
247
- */
248
- interface IStartedCheckoutGKEvent extends BaseEvent {
249
- type: EventType.STARTED_CHECKOUT_GK;
250
- cartValue?: number;
251
- currency?: string;
252
- }
253
- /**
254
- * Mobile added GK event - Tracks when user adds mobile number in GoKwik checkout
255
- */
256
- interface IMobileAddedGKEvent extends BaseEvent {
257
- type: EventType.MOBILE_ADDED_GK;
258
- mobile?: string;
259
- }
260
- /**
261
- * PIN code added GK event - Tracks when user adds PIN code for delivery
262
- */
263
- interface IPinCodeAddedGKEvent extends BaseEvent {
264
- type: EventType.PIN_CODE_ADDED_GK;
265
- pinCode?: string;
266
- }
267
- /**
268
- * Address added GK event - Tracks when user adds a new address
269
- */
270
- interface IAddressAddedGKEvent extends BaseEvent {
271
- type: EventType.ADDRESS_ADDED_GK;
272
- addressId?: string;
273
- }
274
- /**
275
- * Address selected GK event - Tracks when user selects an existing address
276
- */
277
- interface IAddressSelectedGKEvent extends BaseEvent {
278
- type: EventType.ADDRESS_SELECTED_GK;
279
- addressId?: string;
280
- }
281
- /**
282
- * Address completed GK event - Tracks when user completes address information
283
- */
284
- interface IAddressCompletedGKEvent extends BaseEvent {
285
- type: EventType.ADDRESS_COMPLETED_GK;
286
- addressId?: string;
287
- }
288
- /**
289
- * Payment method selected GK event - Tracks when user selects payment method
290
- */
291
- interface IPaymentMethodSelectedGKEvent extends BaseEvent {
292
- type: EventType.PAYMENT_METHOD_SELECTED_GK;
293
- paymentMethod?: string;
294
- }
295
- /**
296
- * Payment completed GK event - Tracks when user completes payment
297
- */
298
- interface IPaymentCompletedGKEvent extends BaseEvent {
299
- type: EventType.PAYMENT_COMPLETED_GK;
300
- amount?: number;
301
- currency?: string;
302
- }
303
- /**
304
- * Order success event - Tracks successful order completion
305
- */
306
- interface IOrderSuccessEvent extends BaseEvent {
307
- type: EventType.ORDER_SUCCESS;
308
- orderId?: string;
309
- amount?: number;
310
- currency?: string;
311
- }
312
- /**
313
- * Order completed event - Tracks final order completion confirmation
314
- */
315
- interface IOrderCompletedEvent extends BaseEvent {
316
- type: EventType.ORDER_COMPLETED;
317
- orderId?: string;
318
- amount?: number;
319
- currency?: string;
320
- }
321
- /**
322
- * Product view KP event - Tracks when user views a product through KwikPass
323
- */
324
- interface IProductViewKPEvent extends BaseEvent {
325
- type: EventType.PRODUCT_VIEW_KP;
326
- productId?: string;
327
- productName?: string;
328
- price?: number;
329
- currency?: string;
330
- category?: string;
331
- }
332
- /**
333
- * Collection view KP event - Tracks when user views a product collection through KwikPass
334
- */
335
- interface ICollectionViewKPEvent extends BaseEvent {
336
- type: EventType.COLLECTION_VIEW_KP;
337
- productId?: string;
338
- productName?: string;
339
- price?: number;
340
- currency?: string;
341
- category?: string;
342
- }
343
- /**
344
- * Page view KP event - Tracks general page views through KwikPass
345
- */
346
- interface IPageViewKPEvent extends BaseEvent {
347
- type: EventType.PAGE_VIEW_KP;
348
- path?: string;
349
- title?: string;
350
- referrer?: string;
351
- }
352
225
  /**
353
226
  * Shopify page view event - Tracks page views specifically for Shopify analytics
354
227
  */
@@ -359,6 +232,6 @@ interface IShopifyPageViewEvent extends BaseEvent {
359
232
  /**
360
233
  * Union type of all possible events
361
234
  */
362
- type TEvent = IPageViewEvent | IAddToCartEvent | IRemoveFromCartEvent | ICartViewedEvent | ISearchEvent | IUserSignupEvent | IUserLoginEvent | IViewContentEvent | IPurchaseEvent | IViewSearchResultsEvent | IBeginCheckoutEvent | ICustomEvent | ISpecificEvent | IAddPaymentInfoEvent | IStartedCheckoutGKEvent | IMobileAddedGKEvent | IAddressSelectedGKEvent | IAddressCompletedGKEvent | IPaymentMethodSelectedGKEvent | IPaymentCompletedGKEvent | IOrderSuccessEvent | IOrderCompletedEvent | IPinCodeAddedGKEvent | IAddressAddedGKEvent | IProductViewKPEvent | ICollectionViewKPEvent | IPageViewKPEvent | IViewedProductEvent | IShopifyPageViewEvent;
235
+ type TEvent = IPageViewEvent | IAddToCartEvent | IRemoveFromCartEvent | ICartViewedEvent | ISearchEvent | IUserSignupEvent | IUserLoginEvent | IViewContentEvent | IPurchaseEvent | IViewSearchResultsEvent | IBeginCheckoutEvent | ICustomEvent | ISpecificEvent | IAddPaymentInfoEvent | IViewedProductEvent | IShopifyPageViewEvent;
363
236
 
364
- export { type BaseEvent, EventType, type IAddPaymentInfoEvent, type IAddToCartEvent, type IAddressAddedGKEvent, type IAddressCompletedGKEvent, type IAddressSelectedGKEvent, type IBeginCheckoutEvent, type ICartViewedEvent, type ICollectionViewKPEvent, type ICustomEvent, type IMobileAddedGKEvent, type IOrderCompletedEvent, type IOrderSuccessEvent, type IPageViewEvent, type IPageViewKPEvent, type IPaymentCompletedGKEvent, type IPaymentMethodSelectedGKEvent, type IPinCodeAddedGKEvent, type IProductViewKPEvent, type IPurchaseEvent, type IRemoveFromCartEvent, type ISearchEvent, type IShopifyPageViewEvent, type ISpecificEvent, type IStartedCheckoutGKEvent, type IUserLoginEvent, type IUserSignupEvent, type IViewContentEvent, type IViewSearchResultsEvent, type IViewedProductEvent, type TEvent };
237
+ export { type BaseEvent, EventType, type IAddPaymentInfoEvent, type IAddToCartEvent, type IBeginCheckoutEvent, type ICartViewedEvent, type ICustomEvent, type IPageViewEvent, type IPurchaseEvent, type IRemoveFromCartEvent, type ISearchEvent, type IShopifyPageViewEvent, type ISpecificEvent, type IUserLoginEvent, type IUserSignupEvent, type IViewContentEvent, type IViewSearchResultsEvent, type IViewedProductEvent, type TEvent };
package/dist/types.d.ts CHANGED
@@ -23,26 +23,6 @@ declare enum EventType {
23
23
  USER_SIGNUP = "user_signup",
24
24
  /** User login tracking */
25
25
  USER_LOGIN = "user_login",
26
- /** Checkout initiation */
27
- STARTED_CHECKOUT_GK = "started_checkout_gk",
28
- /** Contact information collection */
29
- MOBILE_ADDED_GK = "mobile_added_gk",
30
- /** Address management events */
31
- PIN_CODE_ADDED_GK = "pin_code_added_gk",
32
- ADDRESS_ADDED_GK = "address_added_gk",
33
- ADDRESS_SELECTED_GK = "address_selected_gk",
34
- ADDRESS_COMPLETED_GK = "address_completed_gk",
35
- /** Payment flow events */
36
- PAYMENT_METHOD_SELECTED_GK = "payment_method_selected_gk",
37
- PAYMENT_COMPLETED_GK = "payment_completed_gk",
38
- /** Order completion events */
39
- ORDER_SUCCESS = "order_success",
40
- ORDER_COMPLETED = "order_completed",
41
- /** Product interaction tracking through KwikPass */
42
- PRODUCT_VIEW_KP = "product_view_kp",
43
- COLLECTION_VIEW_KP = "collection_view_kp",
44
- /** Page navigation tracking through KwikPass */
45
- PAGE_VIEW_KP = "page_view_kp",
46
26
  /** Shopify analytics integration - Do Not Remove */
47
27
  SHOPIFY_PAGE_VIEW = "shopify_page_view",
48
28
  /** Generic custom event for any tracking needs */
@@ -242,113 +222,6 @@ interface ICustomEvent extends BaseEvent {
242
222
  interface ISpecificEvent extends BaseEvent {
243
223
  type: EventType.SPECIFIC;
244
224
  }
245
- /**
246
- * Started checkout GK event - Tracks when user initiates GoKwik checkout
247
- */
248
- interface IStartedCheckoutGKEvent extends BaseEvent {
249
- type: EventType.STARTED_CHECKOUT_GK;
250
- cartValue?: number;
251
- currency?: string;
252
- }
253
- /**
254
- * Mobile added GK event - Tracks when user adds mobile number in GoKwik checkout
255
- */
256
- interface IMobileAddedGKEvent extends BaseEvent {
257
- type: EventType.MOBILE_ADDED_GK;
258
- mobile?: string;
259
- }
260
- /**
261
- * PIN code added GK event - Tracks when user adds PIN code for delivery
262
- */
263
- interface IPinCodeAddedGKEvent extends BaseEvent {
264
- type: EventType.PIN_CODE_ADDED_GK;
265
- pinCode?: string;
266
- }
267
- /**
268
- * Address added GK event - Tracks when user adds a new address
269
- */
270
- interface IAddressAddedGKEvent extends BaseEvent {
271
- type: EventType.ADDRESS_ADDED_GK;
272
- addressId?: string;
273
- }
274
- /**
275
- * Address selected GK event - Tracks when user selects an existing address
276
- */
277
- interface IAddressSelectedGKEvent extends BaseEvent {
278
- type: EventType.ADDRESS_SELECTED_GK;
279
- addressId?: string;
280
- }
281
- /**
282
- * Address completed GK event - Tracks when user completes address information
283
- */
284
- interface IAddressCompletedGKEvent extends BaseEvent {
285
- type: EventType.ADDRESS_COMPLETED_GK;
286
- addressId?: string;
287
- }
288
- /**
289
- * Payment method selected GK event - Tracks when user selects payment method
290
- */
291
- interface IPaymentMethodSelectedGKEvent extends BaseEvent {
292
- type: EventType.PAYMENT_METHOD_SELECTED_GK;
293
- paymentMethod?: string;
294
- }
295
- /**
296
- * Payment completed GK event - Tracks when user completes payment
297
- */
298
- interface IPaymentCompletedGKEvent extends BaseEvent {
299
- type: EventType.PAYMENT_COMPLETED_GK;
300
- amount?: number;
301
- currency?: string;
302
- }
303
- /**
304
- * Order success event - Tracks successful order completion
305
- */
306
- interface IOrderSuccessEvent extends BaseEvent {
307
- type: EventType.ORDER_SUCCESS;
308
- orderId?: string;
309
- amount?: number;
310
- currency?: string;
311
- }
312
- /**
313
- * Order completed event - Tracks final order completion confirmation
314
- */
315
- interface IOrderCompletedEvent extends BaseEvent {
316
- type: EventType.ORDER_COMPLETED;
317
- orderId?: string;
318
- amount?: number;
319
- currency?: string;
320
- }
321
- /**
322
- * Product view KP event - Tracks when user views a product through KwikPass
323
- */
324
- interface IProductViewKPEvent extends BaseEvent {
325
- type: EventType.PRODUCT_VIEW_KP;
326
- productId?: string;
327
- productName?: string;
328
- price?: number;
329
- currency?: string;
330
- category?: string;
331
- }
332
- /**
333
- * Collection view KP event - Tracks when user views a product collection through KwikPass
334
- */
335
- interface ICollectionViewKPEvent extends BaseEvent {
336
- type: EventType.COLLECTION_VIEW_KP;
337
- productId?: string;
338
- productName?: string;
339
- price?: number;
340
- currency?: string;
341
- category?: string;
342
- }
343
- /**
344
- * Page view KP event - Tracks general page views through KwikPass
345
- */
346
- interface IPageViewKPEvent extends BaseEvent {
347
- type: EventType.PAGE_VIEW_KP;
348
- path?: string;
349
- title?: string;
350
- referrer?: string;
351
- }
352
225
  /**
353
226
  * Shopify page view event - Tracks page views specifically for Shopify analytics
354
227
  */
@@ -359,6 +232,6 @@ interface IShopifyPageViewEvent extends BaseEvent {
359
232
  /**
360
233
  * Union type of all possible events
361
234
  */
362
- type TEvent = IPageViewEvent | IAddToCartEvent | IRemoveFromCartEvent | ICartViewedEvent | ISearchEvent | IUserSignupEvent | IUserLoginEvent | IViewContentEvent | IPurchaseEvent | IViewSearchResultsEvent | IBeginCheckoutEvent | ICustomEvent | ISpecificEvent | IAddPaymentInfoEvent | IStartedCheckoutGKEvent | IMobileAddedGKEvent | IAddressSelectedGKEvent | IAddressCompletedGKEvent | IPaymentMethodSelectedGKEvent | IPaymentCompletedGKEvent | IOrderSuccessEvent | IOrderCompletedEvent | IPinCodeAddedGKEvent | IAddressAddedGKEvent | IProductViewKPEvent | ICollectionViewKPEvent | IPageViewKPEvent | IViewedProductEvent | IShopifyPageViewEvent;
235
+ type TEvent = IPageViewEvent | IAddToCartEvent | IRemoveFromCartEvent | ICartViewedEvent | ISearchEvent | IUserSignupEvent | IUserLoginEvent | IViewContentEvent | IPurchaseEvent | IViewSearchResultsEvent | IBeginCheckoutEvent | ICustomEvent | ISpecificEvent | IAddPaymentInfoEvent | IViewedProductEvent | IShopifyPageViewEvent;
363
236
 
364
- export { type BaseEvent, EventType, type IAddPaymentInfoEvent, type IAddToCartEvent, type IAddressAddedGKEvent, type IAddressCompletedGKEvent, type IAddressSelectedGKEvent, type IBeginCheckoutEvent, type ICartViewedEvent, type ICollectionViewKPEvent, type ICustomEvent, type IMobileAddedGKEvent, type IOrderCompletedEvent, type IOrderSuccessEvent, type IPageViewEvent, type IPageViewKPEvent, type IPaymentCompletedGKEvent, type IPaymentMethodSelectedGKEvent, type IPinCodeAddedGKEvent, type IProductViewKPEvent, type IPurchaseEvent, type IRemoveFromCartEvent, type ISearchEvent, type IShopifyPageViewEvent, type ISpecificEvent, type IStartedCheckoutGKEvent, type IUserLoginEvent, type IUserSignupEvent, type IViewContentEvent, type IViewSearchResultsEvent, type IViewedProductEvent, type TEvent };
237
+ export { type BaseEvent, EventType, type IAddPaymentInfoEvent, type IAddToCartEvent, type IBeginCheckoutEvent, type ICartViewedEvent, type ICustomEvent, type IPageViewEvent, type IPurchaseEvent, type IRemoveFromCartEvent, type ISearchEvent, type IShopifyPageViewEvent, type ISpecificEvent, type IUserLoginEvent, type IUserSignupEvent, type IViewContentEvent, type IViewSearchResultsEvent, type IViewedProductEvent, type TEvent };
package/dist/types.js CHANGED
@@ -37,19 +37,6 @@ var EventType = /* @__PURE__ */ ((EventType2) => {
37
37
  EventType2["VIEW_SEARCH_RESULTS"] = "view_search_results";
38
38
  EventType2["USER_SIGNUP"] = "user_signup";
39
39
  EventType2["USER_LOGIN"] = "user_login";
40
- EventType2["STARTED_CHECKOUT_GK"] = "started_checkout_gk";
41
- EventType2["MOBILE_ADDED_GK"] = "mobile_added_gk";
42
- EventType2["PIN_CODE_ADDED_GK"] = "pin_code_added_gk";
43
- EventType2["ADDRESS_ADDED_GK"] = "address_added_gk";
44
- EventType2["ADDRESS_SELECTED_GK"] = "address_selected_gk";
45
- EventType2["ADDRESS_COMPLETED_GK"] = "address_completed_gk";
46
- EventType2["PAYMENT_METHOD_SELECTED_GK"] = "payment_method_selected_gk";
47
- EventType2["PAYMENT_COMPLETED_GK"] = "payment_completed_gk";
48
- EventType2["ORDER_SUCCESS"] = "order_success";
49
- EventType2["ORDER_COMPLETED"] = "order_completed";
50
- EventType2["PRODUCT_VIEW_KP"] = "product_view_kp";
51
- EventType2["COLLECTION_VIEW_KP"] = "collection_view_kp";
52
- EventType2["PAGE_VIEW_KP"] = "page_view_kp";
53
40
  EventType2["SHOPIFY_PAGE_VIEW"] = "shopify_page_view";
54
41
  EventType2["CUSTOM"] = "custom";
55
42
  EventType2["SPECIFIC"] = "specific";
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * Event types that can be tracked across the application\n * Organized by category for better maintainability and understanding\n */\nexport enum EventType {\n // ============================================================================\n // CORE E-COMMERCE EVENTS\n // Standard events used across all analytics platforms\n // ============================================================================\n\n /** Basic page view tracking */\n PAGE_VIEW = \"page_view\",\n\n /** Product viewing and interaction events */\n VIEW_CONTENT = \"view_content\",\n VIEWED_PRODUCT = \"viewed_product\",\n\n /** Shopping cart events */\n ADD_TO_CART = \"add_to_cart\",\n REMOVE_FROM_CART = \"remove_from_cart\",\n CART_VIEWED = \"cart_viewed\",\n\n /** Checkout flow events */\n INITIATE_CHECKOUT = \"initiate_checkout\",\n ADD_PAYMENT_INFO = \"add_payment_info\",\n PURCHASE = \"purchase\",\n\n /** Search and discovery events */\n SEARCH = \"search\",\n VIEW_SEARCH_RESULTS = \"view_search_results\",\n\n // ============================================================================\n // USER AUTHENTICATION EVENTS\n // Events specific to MoEngage for user lifecycle tracking\n // ============================================================================\n\n /** User account creation tracking */\n USER_SIGNUP = \"user_signup\",\n\n /** User login tracking */\n USER_LOGIN = \"user_login\",\n\n // ============================================================================\n // GOKWIK CHECKOUT EVENTS\n // Complete checkout flow tracking for GoKwik integration\n // ============================================================================\n\n /** Checkout initiation */\n STARTED_CHECKOUT_GK = \"started_checkout_gk\",\n\n /** Contact information collection */\n MOBILE_ADDED_GK = \"mobile_added_gk\",\n\n /** Address management events */\n PIN_CODE_ADDED_GK = \"pin_code_added_gk\",\n ADDRESS_ADDED_GK = \"address_added_gk\",\n ADDRESS_SELECTED_GK = \"address_selected_gk\",\n ADDRESS_COMPLETED_GK = \"address_completed_gk\",\n\n /** Payment flow events */\n PAYMENT_METHOD_SELECTED_GK = \"payment_method_selected_gk\",\n PAYMENT_COMPLETED_GK = \"payment_completed_gk\",\n\n /** Order completion events */\n ORDER_SUCCESS = \"order_success\",\n ORDER_COMPLETED = \"order_completed\",\n\n // ============================================================================\n // KWIKPASS EVENTS\n // Events for KwikPass platform integration (dispatched as custom events)\n // ============================================================================\n\n /** Product interaction tracking through KwikPass */\n PRODUCT_VIEW_KP = \"product_view_kp\",\n COLLECTION_VIEW_KP = \"collection_view_kp\",\n\n /** Page navigation tracking through KwikPass */\n PAGE_VIEW_KP = \"page_view_kp\",\n\n // ============================================================================\n // PLATFORM-SPECIFIC EVENTS\n // Events for specific platform integrations\n // ============================================================================\n\n /** Shopify analytics integration - Do Not Remove */\n SHOPIFY_PAGE_VIEW = \"shopify_page_view\",\n\n // ============================================================================\n // CUSTOM EVENTS\n // Generic events for flexible tracking requirements\n // ============================================================================\n\n /** Generic custom event for any tracking needs */\n CUSTOM = \"custom\",\n\n /** Specific custom event with predefined structure */\n SPECIFIC = \"specific\",\n}\n\n/**\n * Base event interface that all events should implement\n */\nexport interface BaseEvent {\n type: EventType;\n timestamp?: number;\n eventId?: string;\n event_category?: string;\n description?: string;\n [key: string]: any;\n}\n\n// ============================================================================\n// CORE ANALYTICS EVENTS\n// These are the fundamental events used across all analytics platforms\n// ============================================================================\n\n/**\n * Page view event - Tracks when a user views a page\n */\nexport interface IPageViewEvent extends BaseEvent {\n type: EventType.PAGE_VIEW;\n path: string;\n title: string;\n referrer?: string;\n}\n\n/**\n * Viewed product event - Triggered after user views a product for 20+ seconds\n */\nexport interface IViewedProductEvent extends BaseEvent {\n type: EventType.VIEWED_PRODUCT;\n productId: string;\n productName: string;\n price: number;\n currency: string;\n viewDuration?: number;\n}\n\n/**\n * Add to cart event - Tracks when user adds product to cart\n */\nexport interface IAddToCartEvent extends BaseEvent {\n type: EventType.ADD_TO_CART;\n productId: string;\n productName: string;\n price: number;\n currency?: string;\n quantity?: number;\n variant?: string;\n}\n\n/**\n * Remove from cart event - Tracks when user removes product from cart\n */\nexport interface IRemoveFromCartEvent extends BaseEvent {\n type: EventType.REMOVE_FROM_CART;\n productId: string;\n productName: string;\n price: number;\n currency?: string;\n quantity: number;\n variant?: string;\n}\n\n/**\n * Cart viewed event - Tracks when user views their cart\n */\nexport interface ICartViewedEvent extends BaseEvent {\n type: EventType.CART_VIEWED;\n cartId: string;\n products: Array<{\n variantId: string;\n price: number;\n quantity: number;\n }>;\n}\n\n/**\n * Search event - Tracks when user performs a search\n */\nexport interface ISearchEvent extends BaseEvent {\n type: EventType.SEARCH;\n searchTerm: string;\n content_ids: string[];\n resultsCount?: number;\n}\n\n/**\n * Add Payment Info event - Tracks when user adds payment information\n */\nexport interface IAddPaymentInfoEvent extends BaseEvent {\n type: EventType.ADD_PAYMENT_INFO;\n cartValue: number;\n currency?: string;\n itemCount: number;\n paymentType?: string;\n items: Array<{\n productId: string;\n productName: string;\n price: number;\n quantity: number;\n variant?: string;\n }>;\n}\n\n// ============================================================================\n// USER AUTHENTICATION EVENTS\n// Events specific to MoEngage for user authentication tracking\n// ============================================================================\n\n/**\n * User signup event - Tracks when a user creates an account\n */\nexport interface IUserSignupEvent extends BaseEvent {\n type: EventType.USER_SIGNUP;\n userId?: string;\n method?: string;\n success: boolean;\n pagePath: string;\n pageTitle: string;\n timestamp: number;\n customProperties?: Record<string, any>;\n}\n\n/**\n * User login event - Tracks when a user logs into their account\n */\nexport interface IUserLoginEvent extends BaseEvent {\n type: EventType.USER_LOGIN;\n userId?: string;\n method?: string;\n success: boolean;\n pagePath: string;\n pageTitle: string;\n timestamp: number;\n customProperties?: Record<string, any>;\n}\n\n// ============================================================================\n// PLATFORM-SPECIFIC EVENTS\n// Events designed for specific analytics platforms\n// ============================================================================\n\n/**\n * View content event - Facebook Pixel specific event for content viewing\n */\nexport interface IViewContentEvent extends BaseEvent {\n type: EventType.VIEW_CONTENT;\n content_type?: string;\n content_ids?: string[];\n content_name?: string;\n content_category?: string;\n value?: number;\n currency?: string;\n items?: Array<any>;\n}\n\n/**\n * Purchase event - Facebook Pixel specific event for purchase tracking\n */\nexport interface IPurchaseEvent extends BaseEvent {\n type: EventType.PURCHASE;\n orderId?: string;\n cartValue?: number;\n currency?: string;\n itemCount?: number;\n items: Array<{\n productId: string;\n productName: string;\n price: number;\n quantity: number;\n variant?: string;\n }>;\n transaction_id?: string;\n coupon?: string;\n shipping?: number;\n tax?: number;\n discount?: number | string;\n}\n\n/**\n * View search results event - Google Analytics 4 specific event\n */\nexport interface IViewSearchResultsEvent extends BaseEvent {\n type: EventType.VIEW_SEARCH_RESULTS;\n search_term?: string;\n}\n\n/**\n * Begin checkout event - Google Analytics 4 specific event for checkout initiation\n */\nexport interface IBeginCheckoutEvent extends BaseEvent {\n type: EventType.INITIATE_CHECKOUT;\n orderId?: string;\n cartValue: number;\n currency?: string;\n itemCount: number;\n items: Array<{\n productId: string;\n productName: string;\n price: number;\n quantity: number;\n variant?: string;\n }>;\n coupon?: string;\n discount?: number | string;\n}\n\n// ============================================================================\n// CUSTOM EVENTS\n// Generic events for custom tracking needs\n// ============================================================================\n\n/**\n * Custom event - For any custom tracking requirements not covered by standard events\n */\nexport interface ICustomEvent extends BaseEvent {\n type: EventType.CUSTOM;\n}\n\n/**\n * Specific event - For specific tracking requirements with custom properties\n */\nexport interface ISpecificEvent extends BaseEvent {\n type: EventType.SPECIFIC;\n}\n\n// ============================================================================\n// GOKWIK CHECKOUT EVENTS\n// Events specific to GoKwik checkout flow tracking\n// These events track the complete checkout journey from start to completion\n// ============================================================================\n\n/**\n * Started checkout GK event - Tracks when user initiates GoKwik checkout\n */\nexport interface IStartedCheckoutGKEvent extends BaseEvent {\n type: EventType.STARTED_CHECKOUT_GK;\n cartValue?: number;\n currency?: string;\n}\n\n/**\n * Mobile added GK event - Tracks when user adds mobile number in GoKwik checkout\n */\nexport interface IMobileAddedGKEvent extends BaseEvent {\n type: EventType.MOBILE_ADDED_GK;\n mobile?: string;\n}\n\n/**\n * PIN code added GK event - Tracks when user adds PIN code for delivery\n */\nexport interface IPinCodeAddedGKEvent extends BaseEvent {\n type: EventType.PIN_CODE_ADDED_GK;\n pinCode?: string;\n}\n\n/**\n * Address added GK event - Tracks when user adds a new address\n */\nexport interface IAddressAddedGKEvent extends BaseEvent {\n type: EventType.ADDRESS_ADDED_GK;\n addressId?: string;\n}\n\n/**\n * Address selected GK event - Tracks when user selects an existing address\n */\nexport interface IAddressSelectedGKEvent extends BaseEvent {\n type: EventType.ADDRESS_SELECTED_GK;\n addressId?: string;\n}\n\n/**\n * Address completed GK event - Tracks when user completes address information\n */\nexport interface IAddressCompletedGKEvent extends BaseEvent {\n type: EventType.ADDRESS_COMPLETED_GK;\n addressId?: string;\n}\n\n/**\n * Payment method selected GK event - Tracks when user selects payment method\n */\nexport interface IPaymentMethodSelectedGKEvent extends BaseEvent {\n type: EventType.PAYMENT_METHOD_SELECTED_GK;\n paymentMethod?: string;\n}\n\n/**\n * Payment completed GK event - Tracks when user completes payment\n */\nexport interface IPaymentCompletedGKEvent extends BaseEvent {\n type: EventType.PAYMENT_COMPLETED_GK;\n amount?: number;\n currency?: string;\n}\n\n/**\n * Order success event - Tracks successful order completion\n */\nexport interface IOrderSuccessEvent extends BaseEvent {\n type: EventType.ORDER_SUCCESS;\n orderId?: string;\n amount?: number;\n currency?: string;\n}\n\n/**\n * Order completed event - Tracks final order completion confirmation\n */\nexport interface IOrderCompletedEvent extends BaseEvent {\n type: EventType.ORDER_COMPLETED;\n orderId?: string;\n amount?: number;\n currency?: string;\n}\n\n// ============================================================================\n// KWIKPASS EVENTS\n// Events specific to KwikPass platform integration\n// These events are dispatched as custom events for KwikPass to listen to\n// ============================================================================\n\n/**\n * Product view KP event - Tracks when user views a product through KwikPass\n */\nexport interface IProductViewKPEvent extends BaseEvent {\n type: EventType.PRODUCT_VIEW_KP;\n productId?: string;\n productName?: string;\n price?: number;\n currency?: string;\n category?: string;\n}\n\n/**\n * Collection view KP event - Tracks when user views a product collection through KwikPass\n */\nexport interface ICollectionViewKPEvent extends BaseEvent {\n type: EventType.COLLECTION_VIEW_KP;\n productId?: string;\n productName?: string;\n price?: number;\n currency?: string;\n category?: string;\n}\n\n/**\n * Page view KP event - Tracks general page views through KwikPass\n */\nexport interface IPageViewKPEvent extends BaseEvent {\n type: EventType.PAGE_VIEW_KP;\n path?: string;\n title?: string;\n referrer?: string;\n}\n\n// ============================================================================\n// SHOPIFY EVENTS\n// Events specific to Shopify platform integration\n// ============================================================================\n\n/**\n * Shopify page view event - Tracks page views specifically for Shopify analytics\n */\nexport interface IShopifyPageViewEvent extends BaseEvent {\n type: EventType.SHOPIFY_PAGE_VIEW;\n path?: string;\n}\n\n/**\n * Union type of all possible events\n */\nexport type TEvent =\n | IPageViewEvent\n | IAddToCartEvent\n | IRemoveFromCartEvent\n | ICartViewedEvent\n | ISearchEvent\n | IUserSignupEvent\n | IUserLoginEvent\n | IViewContentEvent\n | IPurchaseEvent\n | IViewSearchResultsEvent\n | IBeginCheckoutEvent\n | ICustomEvent\n | ISpecificEvent\n | IAddPaymentInfoEvent\n | IStartedCheckoutGKEvent\n | IMobileAddedGKEvent\n | IAddressSelectedGKEvent\n | IAddressCompletedGKEvent\n | IPaymentMethodSelectedGKEvent\n | IPaymentCompletedGKEvent\n | IOrderSuccessEvent\n | IOrderCompletedEvent\n | IPinCodeAddedGKEvent\n | IAddressAddedGKEvent\n | IProductViewKPEvent\n | ICollectionViewKPEvent\n | IPageViewKPEvent\n | IViewedProductEvent\n | IShopifyPageViewEvent;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIO,IAAK,YAAL,kBAAKA,eAAL;AAOL,EAAAA,WAAA,eAAY;AAGZ,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,oBAAiB;AAGjB,EAAAA,WAAA,iBAAc;AACd,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,iBAAc;AAGd,EAAAA,WAAA,uBAAoB;AACpB,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,cAAW;AAGX,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,yBAAsB;AAQtB,EAAAA,WAAA,iBAAc;AAGd,EAAAA,WAAA,gBAAa;AAQb,EAAAA,WAAA,yBAAsB;AAGtB,EAAAA,WAAA,qBAAkB;AAGlB,EAAAA,WAAA,uBAAoB;AACpB,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,yBAAsB;AACtB,EAAAA,WAAA,0BAAuB;AAGvB,EAAAA,WAAA,gCAA6B;AAC7B,EAAAA,WAAA,0BAAuB;AAGvB,EAAAA,WAAA,mBAAgB;AAChB,EAAAA,WAAA,qBAAkB;AAQlB,EAAAA,WAAA,qBAAkB;AAClB,EAAAA,WAAA,wBAAqB;AAGrB,EAAAA,WAAA,kBAAe;AAQf,EAAAA,WAAA,uBAAoB;AAQpB,EAAAA,WAAA,YAAS;AAGT,EAAAA,WAAA,cAAW;AA5FD,SAAAA;AAAA,GAAA;","names":["EventType"]}
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * Event types that can be tracked across the application\n * Organized by category for better maintainability and understanding\n */\nexport enum EventType {\n // ============================================================================\n // CORE E-COMMERCE EVENTS\n // Standard events used across all analytics platforms\n // ============================================================================\n\n /** Basic page view tracking */\n PAGE_VIEW = \"page_view\",\n\n /** Product viewing and interaction events */\n VIEW_CONTENT = \"view_content\",\n VIEWED_PRODUCT = \"viewed_product\",\n\n /** Shopping cart events */\n ADD_TO_CART = \"add_to_cart\",\n REMOVE_FROM_CART = \"remove_from_cart\",\n CART_VIEWED = \"cart_viewed\",\n\n /** Checkout flow events */\n INITIATE_CHECKOUT = \"initiate_checkout\",\n ADD_PAYMENT_INFO = \"add_payment_info\",\n PURCHASE = \"purchase\",\n\n /** Search and discovery events */\n SEARCH = \"search\",\n VIEW_SEARCH_RESULTS = \"view_search_results\",\n\n // ============================================================================\n // USER AUTHENTICATION EVENTS\n // Events specific to MoEngage for user lifecycle tracking\n // ============================================================================\n\n /** User account creation tracking */\n USER_SIGNUP = \"user_signup\",\n\n /** User login tracking */\n USER_LOGIN = \"user_login\",\n\n // ============================================================================\n // PLATFORM-SPECIFIC EVENTS\n // Events for specific platform integrations\n // ============================================================================\n\n /** Shopify analytics integration - Do Not Remove */\n SHOPIFY_PAGE_VIEW = \"shopify_page_view\",\n\n // ============================================================================\n // CUSTOM EVENTS\n // Generic events for flexible tracking requirements\n // ============================================================================\n\n /** Generic custom event for any tracking needs */\n CUSTOM = \"custom\",\n\n /** Specific custom event with predefined structure */\n SPECIFIC = \"specific\",\n}\n\n/**\n * Base event interface that all events should implement\n */\nexport interface BaseEvent {\n type: EventType;\n timestamp?: number;\n eventId?: string;\n event_category?: string;\n description?: string;\n [key: string]: any;\n}\n\n// ============================================================================\n// CORE ANALYTICS EVENTS\n// These are the fundamental events used across all analytics platforms\n// ============================================================================\n\n/**\n * Page view event - Tracks when a user views a page\n */\nexport interface IPageViewEvent extends BaseEvent {\n type: EventType.PAGE_VIEW;\n path: string;\n title: string;\n referrer?: string;\n}\n\n/**\n * Viewed product event - Triggered after user views a product for 20+ seconds\n */\nexport interface IViewedProductEvent extends BaseEvent {\n type: EventType.VIEWED_PRODUCT;\n productId: string;\n productName: string;\n price: number;\n currency: string;\n viewDuration?: number;\n}\n\n/**\n * Add to cart event - Tracks when user adds product to cart\n */\nexport interface IAddToCartEvent extends BaseEvent {\n type: EventType.ADD_TO_CART;\n productId: string;\n productName: string;\n price: number;\n currency?: string;\n quantity?: number;\n variant?: string;\n}\n\n/**\n * Remove from cart event - Tracks when user removes product from cart\n */\nexport interface IRemoveFromCartEvent extends BaseEvent {\n type: EventType.REMOVE_FROM_CART;\n productId: string;\n productName: string;\n price: number;\n currency?: string;\n quantity: number;\n variant?: string;\n}\n\n/**\n * Cart viewed event - Tracks when user views their cart\n */\nexport interface ICartViewedEvent extends BaseEvent {\n type: EventType.CART_VIEWED;\n cartId: string;\n products: Array<{\n variantId: string;\n price: number;\n quantity: number;\n }>;\n}\n\n/**\n * Search event - Tracks when user performs a search\n */\nexport interface ISearchEvent extends BaseEvent {\n type: EventType.SEARCH;\n searchTerm: string;\n content_ids: string[];\n resultsCount?: number;\n}\n\n/**\n * Add Payment Info event - Tracks when user adds payment information\n */\nexport interface IAddPaymentInfoEvent extends BaseEvent {\n type: EventType.ADD_PAYMENT_INFO;\n cartValue: number;\n currency?: string;\n itemCount: number;\n paymentType?: string;\n items: Array<{\n productId: string;\n productName: string;\n price: number;\n quantity: number;\n variant?: string;\n }>;\n}\n\n// ============================================================================\n// USER AUTHENTICATION EVENTS\n// Events specific to MoEngage for user authentication tracking\n// ============================================================================\n\n/**\n * User signup event - Tracks when a user creates an account\n */\nexport interface IUserSignupEvent extends BaseEvent {\n type: EventType.USER_SIGNUP;\n userId?: string;\n method?: string;\n success: boolean;\n pagePath: string;\n pageTitle: string;\n timestamp: number;\n customProperties?: Record<string, any>;\n}\n\n/**\n * User login event - Tracks when a user logs into their account\n */\nexport interface IUserLoginEvent extends BaseEvent {\n type: EventType.USER_LOGIN;\n userId?: string;\n method?: string;\n success: boolean;\n pagePath: string;\n pageTitle: string;\n timestamp: number;\n customProperties?: Record<string, any>;\n}\n\n// ============================================================================\n// PLATFORM-SPECIFIC EVENTS\n// Events designed for specific analytics platforms\n// ============================================================================\n\n/**\n * View content event - Facebook Pixel specific event for content viewing\n */\nexport interface IViewContentEvent extends BaseEvent {\n type: EventType.VIEW_CONTENT;\n content_type?: string;\n content_ids?: string[];\n content_name?: string;\n content_category?: string;\n value?: number;\n currency?: string;\n items?: Array<any>;\n}\n\n/**\n * Purchase event - Facebook Pixel specific event for purchase tracking\n */\nexport interface IPurchaseEvent extends BaseEvent {\n type: EventType.PURCHASE;\n orderId?: string;\n cartValue?: number;\n currency?: string;\n itemCount?: number;\n items: Array<{\n productId: string;\n productName: string;\n price: number;\n quantity: number;\n variant?: string;\n }>;\n transaction_id?: string;\n coupon?: string;\n shipping?: number;\n tax?: number;\n discount?: number | string;\n}\n\n/**\n * View search results event - Google Analytics 4 specific event\n */\nexport interface IViewSearchResultsEvent extends BaseEvent {\n type: EventType.VIEW_SEARCH_RESULTS;\n search_term?: string;\n}\n\n/**\n * Begin checkout event - Google Analytics 4 specific event for checkout initiation\n */\nexport interface IBeginCheckoutEvent extends BaseEvent {\n type: EventType.INITIATE_CHECKOUT;\n orderId?: string;\n cartValue: number;\n currency?: string;\n itemCount: number;\n items: Array<{\n productId: string;\n productName: string;\n price: number;\n quantity: number;\n variant?: string;\n }>;\n coupon?: string;\n discount?: number | string;\n}\n\n// ============================================================================\n// CUSTOM EVENTS\n// Generic events for custom tracking needs\n// ============================================================================\n\n/**\n * Custom event - For any custom tracking requirements not covered by standard events\n */\nexport interface ICustomEvent extends BaseEvent {\n type: EventType.CUSTOM;\n}\n\n/**\n * Specific event - For specific tracking requirements with custom properties\n */\nexport interface ISpecificEvent extends BaseEvent {\n type: EventType.SPECIFIC;\n}\n\n// ============================================================================\n// SHOPIFY EVENTS\n// Events specific to Shopify platform integration\n// ============================================================================\n\n/**\n * Shopify page view event - Tracks page views specifically for Shopify analytics\n */\nexport interface IShopifyPageViewEvent extends BaseEvent {\n type: EventType.SHOPIFY_PAGE_VIEW;\n path?: string;\n}\n\n/**\n * Union type of all possible events\n */\nexport type TEvent =\n | IPageViewEvent\n | IAddToCartEvent\n | IRemoveFromCartEvent\n | ICartViewedEvent\n | ISearchEvent\n | IUserSignupEvent\n | IUserLoginEvent\n | IViewContentEvent\n | IPurchaseEvent\n | IViewSearchResultsEvent\n | IBeginCheckoutEvent\n | ICustomEvent\n | ISpecificEvent\n | IAddPaymentInfoEvent\n | IViewedProductEvent\n | IShopifyPageViewEvent;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIO,IAAK,YAAL,kBAAKA,eAAL;AAOL,EAAAA,WAAA,eAAY;AAGZ,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,oBAAiB;AAGjB,EAAAA,WAAA,iBAAc;AACd,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,iBAAc;AAGd,EAAAA,WAAA,uBAAoB;AACpB,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,cAAW;AAGX,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,yBAAsB;AAQtB,EAAAA,WAAA,iBAAc;AAGd,EAAAA,WAAA,gBAAa;AAQb,EAAAA,WAAA,uBAAoB;AAQpB,EAAAA,WAAA,YAAS;AAGT,EAAAA,WAAA,cAAW;AAvDD,SAAAA;AAAA,GAAA;","names":["EventType"]}