shopkit-analytics 1.0.1 → 1.0.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/README.md +193 -3
- package/dist/adapters/index.d.mts +3 -2
- package/dist/adapters/index.d.ts +3 -2
- package/dist/adapters/index.js +1220 -615
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/index.mjs +4 -2
- package/dist/{chunk-3TQR5DOP.mjs → chunk-3NR2AKE4.mjs} +1 -31
- package/dist/chunk-3NR2AKE4.mjs.map +1 -0
- package/dist/chunk-4RDPDMGW.mjs +68 -0
- package/dist/chunk-4RDPDMGW.mjs.map +1 -0
- package/dist/{chunk-JVEGG6JV.mjs → chunk-HCA4E2RA.mjs} +19 -13
- package/dist/chunk-HCA4E2RA.mjs.map +1 -0
- package/dist/chunk-NC25KOAF.mjs +156 -0
- package/dist/chunk-NC25KOAF.mjs.map +1 -0
- package/dist/chunk-NGPUKV7E.mjs +46 -0
- package/dist/chunk-NGPUKV7E.mjs.map +1 -0
- package/dist/{chunk-4MZH5OLR.mjs → chunk-NJQ2MOM2.mjs} +1145 -618
- package/dist/chunk-NJQ2MOM2.mjs.map +1 -0
- package/dist/chunk-NKDB4KX2.mjs +2 -0
- package/dist/{chunk-P4OJDCEZ.mjs → chunk-QCS5UARA.mjs} +3 -3
- package/dist/events/index.d.mts +9 -41
- package/dist/events/index.d.ts +9 -41
- package/dist/events/index.js +973 -498
- package/dist/events/index.js.map +1 -1
- package/dist/events/index.mjs +11 -11
- package/dist/experiment/index.d.mts +25 -0
- package/dist/experiment/index.d.ts +25 -0
- package/dist/experiment/index.js +74 -0
- package/dist/experiment/index.js.map +1 -0
- package/dist/experiment/index.mjs +15 -0
- package/dist/experiment/index.mjs.map +1 -0
- package/dist/{index-BnNRgdUv.d.ts → index-D_8w5bL_.d.ts} +87 -17
- package/dist/{index-GODWc1s6.d.mts → index-th6sBtE3.d.mts} +87 -17
- package/dist/index.d.mts +10 -6
- package/dist/index.d.ts +10 -6
- package/dist/index.js +1408 -660
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +31 -10
- package/dist/index.mjs.map +1 -1
- package/dist/services/index.d.mts +51 -0
- package/dist/services/index.d.ts +51 -0
- package/dist/services/index.js +180 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/index.mjs +11 -0
- package/dist/services/index.mjs.map +1 -0
- package/dist/{subscriber-43gnCKWe.d.ts → subscriber-BDAm_BAi.d.ts} +38 -2
- package/dist/{subscriber-sWesj_5p.d.mts → subscriber-BoyOlh9t.d.mts} +38 -2
- package/dist/subscriber-VF3IYUCU.mjs +8 -0
- package/dist/subscriber-VF3IYUCU.mjs.map +1 -0
- package/dist/types-C__2IBCj.d.mts +7 -0
- package/dist/types-C__2IBCj.d.ts +7 -0
- package/dist/types.d.mts +4 -340
- package/dist/types.d.ts +4 -340
- package/dist/types.js +0 -30
- package/dist/types.js.map +1 -1
- package/dist/types.mjs +1 -1
- package/dist/utils/index.d.mts +19 -0
- package/dist/utils/index.d.ts +19 -0
- package/dist/utils/index.js +93 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.mjs +12 -0
- package/dist/utils/index.mjs.map +1 -0
- package/package.json +21 -8
- package/templates/nextjs/README.md +206 -0
- package/templates/nextjs/api-events-route.ts +62 -0
- package/dist/chunk-3TQR5DOP.mjs.map +0 -1
- package/dist/chunk-4MZH5OLR.mjs.map +0 -1
- package/dist/chunk-JVEGG6JV.mjs.map +0 -1
- package/dist/subscriber-IFZJU57V.mjs +0 -8
- /package/dist/{subscriber-IFZJU57V.mjs.map → chunk-NKDB4KX2.mjs.map} +0 -0
- /package/dist/{chunk-P4OJDCEZ.mjs.map → chunk-QCS5UARA.mjs.map} +0 -0
package/dist/adapters/index.mjs
CHANGED
|
@@ -8,8 +8,10 @@ import {
|
|
|
8
8
|
PixelAdapter,
|
|
9
9
|
PostHogAdapter,
|
|
10
10
|
ShopifyAdapter
|
|
11
|
-
} from "../chunk-
|
|
12
|
-
import "../chunk-
|
|
11
|
+
} from "../chunk-NJQ2MOM2.mjs";
|
|
12
|
+
import "../chunk-NGPUKV7E.mjs";
|
|
13
|
+
import "../chunk-4RDPDMGW.mjs";
|
|
14
|
+
import "../chunk-3NR2AKE4.mjs";
|
|
13
15
|
export {
|
|
14
16
|
BaseAdapter,
|
|
15
17
|
GoogleAdapter,
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
// src/types.ts
|
|
4
4
|
var EventType = /* @__PURE__ */ ((EventType2) => {
|
|
5
5
|
EventType2["PRODUCT_VIEW"] = "product_view";
|
|
6
|
-
EventType2["STARTED_ORDER"] = "started_order";
|
|
7
6
|
EventType2["PAGE_VIEW"] = "page_view";
|
|
8
7
|
EventType2["BUTTON_CLICK"] = "button_click";
|
|
9
8
|
EventType2["FORM_SUBMISSION"] = "form_submission";
|
|
@@ -16,11 +15,6 @@ var EventType = /* @__PURE__ */ ((EventType2) => {
|
|
|
16
15
|
EventType2["CHECKOUT_STARTED"] = "checkout_started";
|
|
17
16
|
EventType2["CHECKOUT_COMPLETED"] = "checkout_completed";
|
|
18
17
|
EventType2["SEARCH"] = "search";
|
|
19
|
-
EventType2["CART_PAGE_LAND"] = "cart_page_land";
|
|
20
|
-
EventType2["CLOSE_CART"] = "close_cart";
|
|
21
|
-
EventType2["QUANTITY_CHANGE"] = "quantity_change";
|
|
22
|
-
EventType2["FILTER_APPLIED"] = "filter_applied";
|
|
23
|
-
EventType2["NEWSLETTER_SUBSCRIPTION"] = "newsletter_subscription";
|
|
24
18
|
EventType2["USER_SIGNUP"] = "user_signup";
|
|
25
19
|
EventType2["USER_LOGIN"] = "user_login";
|
|
26
20
|
EventType2["CUSTOM"] = "custom";
|
|
@@ -31,25 +25,11 @@ var EventType = /* @__PURE__ */ ((EventType2) => {
|
|
|
31
25
|
EventType2["FORM_START"] = "form_start";
|
|
32
26
|
EventType2["ADD_PAYMENT_INFO"] = "add_payment_info";
|
|
33
27
|
EventType2["CART_VIEWED"] = "cart_viewed";
|
|
34
|
-
EventType2["PAGES_SCREENS_PER_SESSION"] = "pages_screens_per_session";
|
|
35
28
|
EventType2["VIEW_CONTENT"] = "view_content";
|
|
36
29
|
EventType2["PURCHASE"] = "purchase";
|
|
37
30
|
EventType2["VIEW_SEARCH_RESULTS"] = "view_search_results";
|
|
38
31
|
EventType2["ORDER_PLACED"] = "order_placed";
|
|
39
32
|
EventType2["BEGIN_CHECKOUT"] = "begin_checkout";
|
|
40
|
-
EventType2["ITEM_PURCHASED"] = "item_purchased";
|
|
41
|
-
EventType2["UPDATE_CART"] = "update_cart";
|
|
42
|
-
EventType2["CUSTOMER_REGISTERED"] = "customer_registered";
|
|
43
|
-
EventType2["CUSTOMER_LOGGED_IN"] = "customer_logged_in";
|
|
44
|
-
EventType2["SHOPIFY_CHECKOUT_UPDATED"] = "shopify_checkout_updated";
|
|
45
|
-
EventType2["SHOPIFY_ABANDONED_CHECKOUT"] = "shopify_abandoned_checkout";
|
|
46
|
-
EventType2["SHOPIFY_ORDER_FULFILLED"] = "shopify_order_fulfilled";
|
|
47
|
-
EventType2["SHOPIFY_CHECKOUT_STARTED"] = "shopify_checkout_started";
|
|
48
|
-
EventType2["SHOPIFY_ADD_TO_CART"] = "shopify_add_to_cart";
|
|
49
|
-
EventType2["SHOPIFY_REMOVED_FROM_CART"] = "shopify_removed_from_cart";
|
|
50
|
-
EventType2["SHOPIFY_UPDATE_CART"] = "shopify_update_cart";
|
|
51
|
-
EventType2["SPINFORM_RESULT"] = "spinform_result";
|
|
52
|
-
EventType2["COUPON_COPIED"] = "coupon_copied";
|
|
53
33
|
EventType2["STARTED_CHECKOUT_GK"] = "started_checkout_gk";
|
|
54
34
|
EventType2["MOBILE_ADDED_GK"] = "mobile_added_gk";
|
|
55
35
|
EventType2["ADDRESS_SELECTED_GK"] = "address_selected_gk";
|
|
@@ -60,20 +40,10 @@ var EventType = /* @__PURE__ */ ((EventType2) => {
|
|
|
60
40
|
EventType2["ORDER_COMPLETED"] = "order_completed";
|
|
61
41
|
EventType2["PIN_CODE_ADDED_GK"] = "pin_code_added_gk";
|
|
62
42
|
EventType2["ADDRESS_ADDED_GK"] = "address_added_gk";
|
|
63
|
-
EventType2["KP_MP_PHONE_NUMBER_LOGGED_IN"] = "kp_mp_phone_number_logged_in";
|
|
64
|
-
EventType2["KP_PHONE_NUMBER_LOGGED_IN"] = "kp_phone_number_logged_in";
|
|
65
|
-
EventType2["KP_MP_SHOPIFY_LOGGED_IN"] = "kp_mp_shopify_logged_in";
|
|
66
|
-
EventType2["KP_MP_SUCCESSFULLY_LOGGED_OUT"] = "kp_mp_successfully_logged_out";
|
|
67
|
-
EventType2["KP_WHATSAPP_LOGGED_IN"] = "kp_whatsapp_logged_in";
|
|
68
|
-
EventType2["KP_MP_TRUECALLER_LOGGED_IN"] = "kp_mp_truecaller_logged_in";
|
|
69
|
-
EventType2["KP_MP_WHATSAPP_LOGGED_IN"] = "kp_mp_whatsapp_logged_in";
|
|
70
|
-
EventType2["KP_TRUECALLER_LOGGED_IN"] = "kp_truecaller_logged_in";
|
|
71
|
-
EventType2["KP_SHOPIFY_LOGGED_IN"] = "kp_shopify_logged_in";
|
|
72
|
-
EventType2["KP_SUCCESSFULLY_LOGGED_OUT"] = "kp_successfully_logged_out";
|
|
73
43
|
return EventType2;
|
|
74
44
|
})(EventType || {});
|
|
75
45
|
|
|
76
46
|
export {
|
|
77
47
|
EventType
|
|
78
48
|
};
|
|
79
|
-
//# sourceMappingURL=chunk-
|
|
49
|
+
//# sourceMappingURL=chunk-3NR2AKE4.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * Event types that can be tracked across the application\n */\nexport enum EventType {\n PRODUCT_VIEW = \"product_view\",\n PAGE_VIEW = \"page_view\",\n BUTTON_CLICK = \"button_click\",\n FORM_SUBMISSION = \"form_submission\",\n VIEW_ITEM = \"view_item\",\n VIEWED_PRODUCT = \"viewed_product\",\n CHECKOUT_PAYMENT = \"checkout_payment\",\n COLLECTION_VIEW = \"collection_view\",\n ADD_TO_CART = \"add_to_cart\",\n REMOVE_FROM_CART = \"remove_from_cart\",\n CHECKOUT_STARTED = \"checkout_started\",\n CHECKOUT_COMPLETED = \"checkout_completed\",\n SEARCH = \"search\",\n USER_SIGNUP = \"user_signup\",\n USER_LOGIN = \"user_login\",\n CUSTOM = \"custom\",\n USER_ENGAGEMENT = \"user_engagement\",\n SESSION_START = \"session_start\",\n FIRST_VISIT = \"first_visit\",\n SCROLL = \"scroll\",\n FORM_START = \"form_start\",\n ADD_PAYMENT_INFO = \"add_payment_info\",\n CART_VIEWED = \"cart_viewed\",\n VIEW_CONTENT = \"view_content\",\n PURCHASE = \"purchase\",\n VIEW_SEARCH_RESULTS = \"view_search_results\",\n ORDER_PLACED = \"order_placed\",\n BEGIN_CHECKOUT = \"begin_checkout\",\n\n // GoKwik Checkout events (actually used)\n STARTED_CHECKOUT_GK = \"started_checkout_gk\",\n MOBILE_ADDED_GK = \"mobile_added_gk\",\n ADDRESS_SELECTED_GK = \"address_selected_gk\",\n ADDRESS_COMPLETED_GK = \"address_completed_gk\",\n PAYMENT_METHOD_SELECTED_GK = \"payment_method_selected_gk\",\n PAYMENT_COMPLETED_GK = \"payment_completed_gk\",\n ORDER_SUCCESS = \"order_success\",\n ORDER_COMPLETED = \"order_completed\",\n PIN_CODE_ADDED_GK = \"pin_code_added_gk\",\n ADDRESS_ADDED_GK = \"address_added_gk\",\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 * Page view event\n */\nexport interface IPageViewEvent extends BaseEvent {\n type: EventType.PAGE_VIEW;\n path: string;\n title: string;\n referrer?: string;\n // GA4 specific parameters\n batch_ordering_id?: string;\n batch_page_id?: string;\n campaign?: string;\n campaign_id?: string;\n content?: string;\n debug_mode?: boolean;\n engagement_time_msec?: number;\n entrances?: number;\n ga_session_id?: string;\n ga_session_number?: number;\n gclid?: string;\n ignore_referrer?: boolean;\n medium?: string;\n page_location?: string;\n page_path?: string;\n page_referrer?: string;\n page_title?: string;\n page_source?: string;\n page_term?: string;\n user_id?: string;\n user_properties?: Record<string, any>;\n session_engaged?: boolean;\n}\n\n/**\n * User engagement event\n */\nexport interface IUserEngagementEvent extends BaseEvent {\n type: EventType.USER_ENGAGEMENT;\n engagementTime?: number; // in seconds\n pagePath?: string;\n pageTitle?: string;\n scrollDepth?: number; // in percentage\n formId?: string;\n formName?: string;\n formFields?: Array<{\n fieldName: string;\n fieldValue: string;\n }>;\n buttonId?: string;\n buttonText?: string;\n location?: string;\n customProperties?: Record<string, any>;\n // GA4 specific parameters\n batch_ordering_id?: string;\n batch_page_id?: string;\n campaign?: string;\n ga_session_id?: string;\n ga_session_number?: number;\n gclid?: string;\n ignore_referrer?: boolean;\n medium?: string;\n page_location?: string;\n page_path?: string;\n page_referrer?: string;\n page_title?: string;\n source?: string;\n srsltid?: string;\n term?: string;\n user_id?: string;\n user_properties?: Record<string, any>;\n session_engaged?: boolean;\n}\n\n/**\n * Session start event\n */\nexport interface ISessionStartEvent extends BaseEvent {\n type: EventType.SESSION_START;\n sessionId: string;\n userId?: string;\n userAgent?: string;\n referrer?: string;\n pagePath: string;\n pageTitle: string;\n timestamp: number;\n customProperties?: Record<string, any>;\n}\n\n/**\n * First visit event\n */\nexport interface IFirstVisitEvent extends BaseEvent {\n type: EventType.FIRST_VISIT;\n userId?: string;\n userAgent?: string;\n referrer?: string;\n pagePath: string;\n pageTitle: string;\n timestamp: number;\n customProperties?: Record<string, any>;\n}\n\n/**\n * Scroll event\n */\nexport interface IScrollEvent extends BaseEvent {\n type: EventType.SCROLL;\n scrollDepth: number; // in percentage\n pagePath: string;\n pageTitle: string;\n timestamp: number;\n customProperties?: Record<string, any>;\n // GA4 specific parameters\n batch_ordering_id?: string;\n batch_page_id?: string;\n engagement_time_msec?: number;\n ga_session_id?: string;\n ga_session_number?: number;\n ignore_referrer?: boolean;\n page_location?: string;\n page_referrer?: string;\n page_title?: string;\n percent_scrolled?: number;\n}\n\n/**\n * Form start event\n */\nexport interface IFormStartEvent extends BaseEvent {\n type: EventType.FORM_START;\n formId: string;\n formName?: string;\n pagePath: string;\n pageTitle: string;\n timestamp: number;\n customProperties?: Record<string, any>;\n}\n\n/**\n * Form submission event\n */\nexport interface IFormSubmissionEvent extends BaseEvent {\n type: EventType.FORM_SUBMISSION;\n formId: string;\n formName?: string;\n success: boolean;\n pagePath: string;\n pageTitle: string;\n timestamp: number;\n customProperties?: Record<string, any>;\n}\n\n/**\n * User signup event\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\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 * Button click event\n */\nexport interface IButtonClickEvent extends BaseEvent {\n type: EventType.BUTTON_CLICK;\n buttonId?: string;\n buttonText?: string;\n location: string;\n}\n\n/**\n * View item event for e-commerce tracking\n */\nexport interface IViewItemEvent extends BaseEvent {\n type: EventType.VIEW_ITEM;\n currency: string;\n value: number;\n items: Array<{\n item_id: string;\n item_name: string;\n price: number;\n currency: string;\n }>;\n // GA4 specific parameters\n batch_ordering_id?: string;\n batch_page_id?: string;\n campaign?: string;\n ecomm_pagetype?: string;\n ecomm_prodid?: string;\n ecomm_totalvalue?: number;\n engagement_time_msec?: number;\n ga_session_id?: string;\n ga_session_number?: number;\n gclid?: string;\n ignore_referrer?: boolean;\n medium?: string;\n page_location?: string;\n page_path?: string;\n page_referrer?: string;\n page_title?: string;\n source?: string;\n srsltid?: string;\n term?: string;\n user_id?: string;\n user_properties?: Record<string, any>;\n session_engaged?: boolean;\n}\n\n/**\n * Checkout payment event\n */\nexport interface ICheckoutPaymentEvent extends BaseEvent {\n type: EventType.CHECKOUT_PAYMENT;\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 }>;\n}\n\n/**\n * Viewed product event after 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\nexport interface IPCollectionViewEvent extends BaseEvent {\n type: EventType.COLLECTION_VIEW;\n productId: string;\n productName: string;\n price?: number;\n currency?: string;\n category?: string;\n}\n\n/**\n * Add to cart event\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 // GA4 specific parameters\n batch_ordering_id?: string;\n batch_page_id?: string;\n ecomm_pagetype?: string;\n ecomm_prodid?: string;\n ecomm_totalvalue?: number;\n value?: number;\n engagement_time_msec?: number;\n ga_session_id?: string;\n ga_session_number?: number;\n ignore_referrer?: boolean;\n page_location?: string;\n page_referrer?: string;\n page_title?: string;\n user_id?: string;\n user_properties?: Record<string, any>;\n session_engaged?: boolean;\n}\n\n/**\n * Remove from cart event\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 * Checkout started event\n */\nexport interface ICheckoutStartedEvent extends BaseEvent {\n type: EventType.CHECKOUT_STARTED;\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 * Checkout completed event\n */\nexport interface ICheckoutCompletedEvent extends BaseEvent {\n type: EventType.CHECKOUT_COMPLETED;\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}\n\n/**\n * Cart viewed event\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\n */\nexport interface ISearchEvent extends BaseEvent {\n type: EventType.SEARCH;\n searchTerm: string;\n content_ids: string[];\n resultsCount?: number;\n}\n\n/**\n * View content event (for Facebook Pixel ViewContent)\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 // GA4 specific parameters\n batch_ordering_id?: string;\n batch_page_id?: string;\n campaign?: string;\n ga_session_id?: string;\n engagement_time_msec?: number;\n session_engaged?: boolean;\n page_title?: string;\n page_location?: string;\n page_referrer?: string;\n user_id?: string;\n user_properties?: Record<string, any>;\n}\n\n/**\n * Purchase event (for Facebook Pixel Purchase)\n */\nexport interface IPurchaseEvent extends BaseEvent {\n type: EventType.PURCHASE;\n value: number;\n currency?: string;\n content_type?: string;\n content_ids?: string[];\n num_items?: number;\n contents?: Array<{\n id: string;\n quantity: number;\n item_price?: number;\n }>;\n transaction_id?: string;\n coupon?: string;\n shipping?: number;\n tax?: number;\n items?: Array<any>;\n // GA4 specific parameters\n batch_ordering_id?: string;\n batch_page_id?: string;\n campaign?: string;\n ga_session_id?: string;\n engagement_time_msec?: number;\n session_engaged?: boolean;\n page_title?: string;\n page_location?: string;\n page_referrer?: string;\n user_id?: string;\n user_properties?: Record<string, any>;\n}\n\n/**\n * View search results event (for GA4)\n */\nexport interface IViewSearchResultsEvent extends BaseEvent {\n type: EventType.VIEW_SEARCH_RESULTS;\n search_term?: string;\n // GA4 specific parameters\n batch_ordering_id?: string;\n batch_page_id?: string;\n campaign?: string;\n campaign_id?: string;\n content?: string;\n ga_session_id?: string;\n ga_session_number?: number;\n gclid?: string;\n medium?: string;\n page_location?: string;\n page_path?: string;\n page_referrer?: string;\n page_title?: string;\n source?: string;\n srsltid?: string;\n term?: string;\n user_id?: string;\n user_properties?: Record<string, any>;\n session_engaged?: boolean;\n engagement_time_msec?: number;\n}\n\n/**\n * Order placed event (for GA4)\n */\nexport interface IOrderPlacedEvent extends BaseEvent {\n type: EventType.ORDER_PLACED;\n transaction_id?: string;\n order_id?: string;\n total_amount?: number;\n value: number;\n currency?: string;\n items?: Array<any>;\n // GA4 specific parameters\n batch_ordering_id?: string;\n batch_page_id?: string;\n coupon?: string;\n discount?: number;\n engagement_time_msec?: number;\n ga_session_id?: string;\n ga_session_number?: number;\n ignore_referrer?: boolean;\n page_location?: string;\n page_referrer?: string;\n page_title?: string;\n payment_type?: string;\n shipping?: number;\n shipping_name?: string;\n tax?: number;\n user_id?: string;\n user_properties?: Record<string, any>;\n session_engaged?: boolean;\n}\n\n/**\n * Begin checkout event (for GA4)\n */\nexport interface IBeginCheckoutEvent extends BaseEvent {\n type: EventType.BEGIN_CHECKOUT;\n currency?: string;\n value: number;\n coupon?: string;\n items?: Array<any>;\n // GA4 specific parameters\n batch_ordering_id?: string;\n batch_page_id?: string;\n ecomm_pagetype?: string;\n ecomm_prodid?: string;\n ecomm_totalvalue?: number;\n engagement_time_msec?: number;\n ga_session_id?: string;\n ga_session_number?: number;\n ignore_referrer?: boolean;\n page_location?: string;\n page_referrer?: string;\n page_title?: string;\n user_id?: string;\n user_properties?: Record<string, any>;\n session_engaged?: boolean;\n}\n\n/**\n * Custom event for any other tracking needs\n */\nexport interface ICustomEvent extends BaseEvent {\n type: EventType.CUSTOM;\n name: string;\n properties?: Record<string, any>;\n}\n\n/**\n * Add Payment Info event\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 * Started checkout GK event\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\n */\nexport interface IMobileAddedGKEvent extends BaseEvent {\n type: EventType.MOBILE_ADDED_GK;\n mobile?: string;\n}\n\n/**\n * Address selected GK event\n */\nexport interface IAddressSelectedGKEvent extends BaseEvent {\n type: EventType.ADDRESS_SELECTED_GK;\n addressId?: string;\n}\n\n/**\n * Address completed GK event\n */\nexport interface IAddressCompletedGKEvent extends BaseEvent {\n type: EventType.ADDRESS_COMPLETED_GK;\n addressId?: string;\n}\n\n/**\n * Payment method selected GK event\n */\nexport interface IPaymentMethodSelectedGKEvent extends BaseEvent {\n type: EventType.PAYMENT_METHOD_SELECTED_GK;\n paymentMethod?: string;\n}\n\n/**\n * Payment completed GK event\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\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\n */\nexport interface IOrderCompletedEvent extends BaseEvent {\n type: EventType.ORDER_COMPLETED;\n orderId?: string;\n amount?: number;\n currency?: string;\n}\n\n/**\n * PIN code added GK event\n */\nexport interface IPinCodeAddedGKEvent extends BaseEvent {\n type: EventType.PIN_CODE_ADDED_GK;\n pinCode?: string;\n}\n\n/**\n * Address added GK event\n */\nexport interface IAddressAddedGKEvent extends BaseEvent {\n type: EventType.ADDRESS_ADDED_GK;\n addressId?: string;\n}\n\n/**\n * Product view event\n */\nexport interface IProductViewEvent extends BaseEvent {\n type: EventType.PRODUCT_VIEW;\n event_category: string;\n description: string;\n productId: string;\n productName: string;\n price: number;\n currency?: string;\n category?: string;\n}\n\n/**\n * Union type of all possible events\n */\nexport type TEvent =\n | IProductViewEvent\n | IPageViewEvent\n | IButtonClickEvent\n | IFormSubmissionEvent\n | IViewItemEvent\n | IPCollectionViewEvent\n | IAddToCartEvent\n | IRemoveFromCartEvent\n | ICheckoutStartedEvent\n | ICheckoutCompletedEvent\n | ICartViewedEvent\n | ISearchEvent\n | IUserSignupEvent\n | IUserLoginEvent\n | IViewContentEvent\n | IPurchaseEvent\n | IViewSearchResultsEvent\n | IOrderPlacedEvent\n | IBeginCheckoutEvent\n | ICustomEvent\n | IUserEngagementEvent\n | ISessionStartEvent\n | IFirstVisitEvent\n | IScrollEvent\n | IFormStartEvent\n | IAddPaymentInfoEvent\n | IStartedCheckoutGKEvent\n | IMobileAddedGKEvent\n | IAddressSelectedGKEvent\n | IAddressCompletedGKEvent\n | IPaymentMethodSelectedGKEvent\n | IPaymentCompletedGKEvent\n | IOrderSuccessEvent\n | IOrderCompletedEvent\n | IPinCodeAddedGKEvent\n | IAddressAddedGKEvent\n | IViewedProductEvent\n | ICheckoutPaymentEvent;\n"],"mappings":";;;AAGO,IAAK,YAAL,kBAAKA,eAAL;AACL,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,eAAY;AACZ,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,qBAAkB;AAClB,EAAAA,WAAA,eAAY;AACZ,EAAAA,WAAA,oBAAiB;AACjB,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,qBAAkB;AAClB,EAAAA,WAAA,iBAAc;AACd,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,wBAAqB;AACrB,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,iBAAc;AACd,EAAAA,WAAA,gBAAa;AACb,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,qBAAkB;AAClB,EAAAA,WAAA,mBAAgB;AAChB,EAAAA,WAAA,iBAAc;AACd,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,gBAAa;AACb,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,iBAAc;AACd,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,cAAW;AACX,EAAAA,WAAA,yBAAsB;AACtB,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,oBAAiB;AAGjB,EAAAA,WAAA,yBAAsB;AACtB,EAAAA,WAAA,qBAAkB;AAClB,EAAAA,WAAA,yBAAsB;AACtB,EAAAA,WAAA,0BAAuB;AACvB,EAAAA,WAAA,gCAA6B;AAC7B,EAAAA,WAAA,0BAAuB;AACvB,EAAAA,WAAA,mBAAgB;AAChB,EAAAA,WAAA,qBAAkB;AAClB,EAAAA,WAAA,uBAAoB;AACpB,EAAAA,WAAA,sBAAmB;AAxCT,SAAAA;AAAA,GAAA;","names":["EventType"]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/utils/event-id.ts
|
|
4
|
+
function generateEventId(eventType) {
|
|
5
|
+
const timestamp = Date.now();
|
|
6
|
+
const randomString = Math.random().toString(36).substring(2, 8);
|
|
7
|
+
return `${timestamp}_${randomString}_${eventType}`;
|
|
8
|
+
}
|
|
9
|
+
function getBrowserInfo() {
|
|
10
|
+
if (typeof window === "undefined") {
|
|
11
|
+
return {};
|
|
12
|
+
}
|
|
13
|
+
const userAgent = navigator.userAgent;
|
|
14
|
+
const fbc = getFacebookClickId();
|
|
15
|
+
const fbp = getFacebookBrowserId();
|
|
16
|
+
return {
|
|
17
|
+
clientUserAgent: userAgent,
|
|
18
|
+
fbc,
|
|
19
|
+
fbp
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function getFacebookClickId() {
|
|
23
|
+
if (typeof window === "undefined") {
|
|
24
|
+
return void 0;
|
|
25
|
+
}
|
|
26
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
27
|
+
const fbclid = urlParams.get("fbclid");
|
|
28
|
+
if (fbclid) {
|
|
29
|
+
return `fb.1.${Date.now()}.${fbclid}`;
|
|
30
|
+
}
|
|
31
|
+
const cookies = document.cookie.split(";");
|
|
32
|
+
for (const cookie of cookies) {
|
|
33
|
+
const [name, value] = cookie.trim().split("=");
|
|
34
|
+
if (name === "_fbc") {
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return void 0;
|
|
39
|
+
}
|
|
40
|
+
function getFacebookBrowserId() {
|
|
41
|
+
if (typeof window === "undefined") {
|
|
42
|
+
return void 0;
|
|
43
|
+
}
|
|
44
|
+
const cookies = document.cookie.split(";");
|
|
45
|
+
for (const cookie of cookies) {
|
|
46
|
+
const [name, value] = cookie.trim().split("=");
|
|
47
|
+
if (name === "_fbp") {
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return void 0;
|
|
52
|
+
}
|
|
53
|
+
function getClientIpAddress(request) {
|
|
54
|
+
if (!request) {
|
|
55
|
+
return void 0;
|
|
56
|
+
}
|
|
57
|
+
const forwarded = request.headers.get("x-forwarded-for");
|
|
58
|
+
const realIp = request.headers.get("x-real-ip");
|
|
59
|
+
const cfConnectingIp = request.headers.get("cf-connecting-ip");
|
|
60
|
+
return forwarded?.split(",")[0] || realIp || cfConnectingIp || void 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export {
|
|
64
|
+
generateEventId,
|
|
65
|
+
getBrowserInfo,
|
|
66
|
+
getClientIpAddress
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=chunk-4RDPDMGW.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/event-id.ts"],"sourcesContent":["/**\n * Generate a unique event ID for deduplication\n * Format: timestamp_randomString_eventType\n */\nexport function generateEventId(eventType: string): string {\n const timestamp = Date.now();\n const randomString = Math.random().toString(36).substring(2, 8);\n return `${timestamp}_${randomString}_${eventType}`;\n}\n\n/**\n * Extract browser information for CAPI user data\n */\nexport function getBrowserInfo(): {\n clientUserAgent?: string;\n fbc?: string;\n fbp?: string;\n} {\n if (typeof window === \"undefined\") {\n return {};\n }\n\n const userAgent = navigator.userAgent;\n\n // Get Facebook click ID from URL or cookies\n const fbc = getFacebookClickId();\n const fbp = getFacebookBrowserId();\n\n return {\n clientUserAgent: userAgent,\n fbc,\n fbp,\n };\n}\n\n/**\n * Get Facebook click ID (fbc) from URL parameters or cookies\n */\nfunction getFacebookClickId(): string | undefined {\n if (typeof window === \"undefined\") {\n return undefined;\n }\n\n // Check URL parameters first\n const urlParams = new URLSearchParams(window.location.search);\n const fbclid = urlParams.get(\"fbclid\");\n\n if (fbclid) {\n return `fb.1.${Date.now()}.${fbclid}`;\n }\n\n // Check cookies\n const cookies = document.cookie.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 Facebook browser ID (fbp) from cookies\n */\nfunction getFacebookBrowserId(): string | undefined {\n if (typeof window === \"undefined\") {\n return undefined;\n }\n\n const cookies = document.cookie.split(\";\");\n for (const cookie of cookies) {\n const [name, value] = cookie.trim().split(\"=\");\n if (name === \"_fbp\") {\n return value;\n }\n }\n\n return undefined;\n}\n\n/**\n * Get client IP address (this will be handled server-side)\n */\nexport function getClientIpAddress(request?: Request): string | undefined {\n if (!request) {\n return undefined;\n }\n\n // Try different headers for IP address\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"],"mappings":";;;AAIO,SAAS,gBAAgB,WAA2B;AACzD,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,eAAe,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC;AAC9D,SAAO,GAAG,SAAS,IAAI,YAAY,IAAI,SAAS;AAClD;AAKO,SAAS,iBAId;AACA,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,YAAY,UAAU;AAG5B,QAAM,MAAM,mBAAmB;AAC/B,QAAM,MAAM,qBAAqB;AAEjC,SAAO;AAAA,IACL,iBAAiB;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AACF;AAKA,SAAS,qBAAyC;AAChD,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO;AAAA,EACT;AAGA,QAAM,YAAY,IAAI,gBAAgB,OAAO,SAAS,MAAM;AAC5D,QAAM,SAAS,UAAU,IAAI,QAAQ;AAErC,MAAI,QAAQ;AACV,WAAO,QAAQ,KAAK,IAAI,CAAC,IAAI,MAAM;AAAA,EACrC;AAGA,QAAM,UAAU,SAAS,OAAO,MAAM,GAAG;AACzC,aAAW,UAAU,SAAS;AAC5B,UAAM,CAAC,MAAM,KAAK,IAAI,OAAO,KAAK,EAAE,MAAM,GAAG;AAC7C,QAAI,SAAS,QAAQ;AACnB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,uBAA2C;AAClD,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,SAAS,OAAO,MAAM,GAAG;AACzC,aAAW,UAAU,SAAS;AAC5B,UAAM,CAAC,MAAM,KAAK,IAAI,OAAO,KAAK,EAAE,MAAM,GAAG;AAC7C,QAAI,SAAS,QAAQ;AACnB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,mBAAmB,SAAuC;AACxE,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAGA,QAAM,YAAY,QAAQ,QAAQ,IAAI,iBAAiB;AACvD,QAAM,SAAS,QAAQ,QAAQ,IAAI,WAAW;AAC9C,QAAM,iBAAiB,QAAQ,QAAQ,IAAI,kBAAkB;AAE7D,SAAO,WAAW,MAAM,GAAG,EAAE,CAAC,KAAK,UAAU,kBAAkB;AACjE;","names":[]}
|
|
@@ -33,19 +33,24 @@ var EventPublisher = class _EventPublisher {
|
|
|
33
33
|
/**
|
|
34
34
|
* Publish an event to all subscribers
|
|
35
35
|
* @param event The event to publish
|
|
36
|
+
* @param params Optional adapter-specific parameters
|
|
36
37
|
*/
|
|
37
|
-
publish(event) {
|
|
38
|
+
publish(event, params) {
|
|
38
39
|
try {
|
|
39
40
|
console.log("EventPublisher: Received event", {
|
|
40
41
|
type: event.type,
|
|
41
|
-
data: event
|
|
42
|
+
data: event,
|
|
43
|
+
params
|
|
42
44
|
});
|
|
43
45
|
const eventWithTimestamp = !event.timestamp ? { ...event, timestamp: Date.now() } : event;
|
|
44
|
-
console.log(
|
|
46
|
+
console.log(
|
|
47
|
+
"EventPublisher: Number of subscribers:",
|
|
48
|
+
this.subscribers.length
|
|
49
|
+
);
|
|
45
50
|
for (const subscriber of this.subscribers) {
|
|
46
51
|
try {
|
|
47
52
|
console.log("EventPublisher: Notifying subscriber");
|
|
48
|
-
subscriber(eventWithTimestamp);
|
|
53
|
+
subscriber(eventWithTimestamp, params);
|
|
49
54
|
console.log("EventPublisher: Subscriber notified successfully");
|
|
50
55
|
} catch (error) {
|
|
51
56
|
console.error("EventPublisher: Error in subscriber:", error);
|
|
@@ -58,9 +63,9 @@ var EventPublisher = class _EventPublisher {
|
|
|
58
63
|
}
|
|
59
64
|
};
|
|
60
65
|
var eventPublisher = EventPublisher.getInstance();
|
|
61
|
-
function publishEvent(event) {
|
|
66
|
+
function publishEvent(event, params) {
|
|
62
67
|
try {
|
|
63
|
-
eventPublisher.publish(event);
|
|
68
|
+
eventPublisher.publish(event, params);
|
|
64
69
|
} catch (error) {
|
|
65
70
|
console.error("Error in publishEvent helper:", error);
|
|
66
71
|
}
|
|
@@ -150,18 +155,19 @@ var EventSubscriber = class _EventSubscriber {
|
|
|
150
155
|
/**
|
|
151
156
|
* Handle an event by forwarding it to all enabled adapters
|
|
152
157
|
* @param event The event to handle
|
|
158
|
+
* @param params Optional adapter-specific parameters
|
|
153
159
|
*/
|
|
154
|
-
handleEvent(event) {
|
|
155
|
-
console.log("Handling event:", event.type);
|
|
160
|
+
handleEvent(event, params) {
|
|
161
|
+
console.log("Handling event:", event.type, "with params:", params);
|
|
156
162
|
if (!this.initialized) {
|
|
157
163
|
console.log("Subscriber not initialized, queueing event");
|
|
158
|
-
this.eventQueue.push(event);
|
|
164
|
+
this.eventQueue.push({ event, params });
|
|
159
165
|
return;
|
|
160
166
|
}
|
|
161
167
|
for (const adapter of this.adapters) {
|
|
162
168
|
if (adapter.isEnabled()) {
|
|
163
169
|
console.log(`Forwarding event to adapter: ${adapter.name}`);
|
|
164
|
-
adapter.trackEvent(event).catch((error) => {
|
|
170
|
+
adapter.trackEvent(event, params).catch((error) => {
|
|
165
171
|
console.error(
|
|
166
172
|
`Error tracking event in adapter "${adapter.name}":`,
|
|
167
173
|
error
|
|
@@ -180,8 +186,8 @@ var EventSubscriber = class _EventSubscriber {
|
|
|
180
186
|
return;
|
|
181
187
|
}
|
|
182
188
|
console.log(`Processing ${this.eventQueue.length} queued events.`);
|
|
183
|
-
for (const event of this.eventQueue) {
|
|
184
|
-
this.handleEvent(event);
|
|
189
|
+
for (const { event, params } of this.eventQueue) {
|
|
190
|
+
this.handleEvent(event, params);
|
|
185
191
|
}
|
|
186
192
|
this.eventQueue = [];
|
|
187
193
|
}
|
|
@@ -210,4 +216,4 @@ export {
|
|
|
210
216
|
publishEvent,
|
|
211
217
|
eventSubscriber
|
|
212
218
|
};
|
|
213
|
-
//# sourceMappingURL=chunk-
|
|
219
|
+
//# sourceMappingURL=chunk-HCA4E2RA.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/events/publisher.ts","../src/events/subscriber.ts"],"sourcesContent":["import type { TEvent } from \"../types\";\nimport type { TAdapterParams } from \"../adapter-params\";\n\n/**\n * EventPublisher class responsible for publishing events to subscribers\n */\nclass EventPublisher {\n private static instance: EventPublisher;\n private subscribers: Array<(event: TEvent, params?: TAdapterParams) => void> =\n [];\n\n /**\n * Private constructor to enforce singleton pattern\n */\n private constructor() {}\n\n /**\n * Get the singleton instance of EventPublisher\n */\n public static getInstance(): EventPublisher {\n if (!EventPublisher.instance) {\n EventPublisher.instance = new EventPublisher();\n }\n return EventPublisher.instance;\n }\n\n /**\n * Subscribe to events\n * @param callback Function to be called when an event is published\n * @returns Unsubscribe function\n */\n public subscribe(\n callback: (event: TEvent, params?: TAdapterParams) => void\n ): () => void {\n this.subscribers.push(callback);\n\n // Return unsubscribe function\n return () => {\n this.subscribers = this.subscribers.filter(\n (subscriber) => subscriber !== callback\n );\n };\n }\n\n /**\n * Publish an event to all subscribers\n * @param event The event to publish\n * @param params Optional adapter-specific parameters\n */\n public publish(event: TEvent, params?: TAdapterParams): void {\n try {\n console.log(\"EventPublisher: Received event\", {\n type: event.type,\n data: event,\n params: params,\n });\n\n // Add timestamp if not already present\n const eventWithTimestamp = !event.timestamp\n ? { ...event, timestamp: Date.now() }\n : event;\n\n console.log(\n \"EventPublisher: Number of subscribers:\",\n this.subscribers.length\n );\n\n // Notify all subscribers\n for (const subscriber of this.subscribers) {\n try {\n console.log(\"EventPublisher: Notifying subscriber\");\n subscriber(eventWithTimestamp, params);\n console.log(\"EventPublisher: Subscriber notified successfully\");\n } catch (error) {\n console.error(\"EventPublisher: Error in subscriber:\", error);\n // Continue with other subscribers even if one fails\n }\n }\n\n console.log(\"EventPublisher: Event processing completed\");\n } catch (error) {\n console.error(\"Error publishing event:\", error, event);\n // Silently fail to prevent app crashes due to event publishing issues\n }\n }\n}\n\n// Export singleton instance\nexport const eventPublisher = EventPublisher.getInstance();\n\n/**\n * Helper function to publish events\n * @param event The event to publish\n * @param params Optional adapter-specific parameters\n */\nexport function publishEvent(event: TEvent, params?: TAdapterParams): void {\n try {\n eventPublisher.publish(event, params);\n } catch (error) {\n console.error(\"Error in publishEvent helper:\", error);\n // Silently fail to prevent app crashes due to event publishing issues\n }\n}\n","import type { TEvent } from \"../types\";\nimport type { TAdapterParams } from \"../adapter-params\";\nimport { eventPublisher } from \"./publisher\";\n\n/**\n * Interface for tracking adapters\n */\nexport interface TrackingAdapter {\n /**\n * Name of the tracking adapter\n */\n name: string;\n\n /**\n * Whether the adapter is enabled\n */\n isEnabled: () => boolean;\n\n /**\n * Initialize the adapter\n */\n initialize: () => Promise<void>;\n\n /**\n * Track an event\n */\n trackEvent: (event: TEvent, params?: TAdapterParams) => Promise<void>;\n}\n\n/**\n * EventSubscriber class responsible for managing tracking adapters and forwarding events\n */\nclass EventSubscriber {\n private static instance: EventSubscriber;\n private adapters: TrackingAdapter[] = [];\n private initialized = false;\n private eventQueue: Array<{ event: TEvent; params?: TAdapterParams }> = [];\n private unsubscribe: (() => void) | null = null;\n\n /**\n * Private constructor to enforce singleton pattern\n */\n private constructor() {}\n\n /**\n * Get the singleton instance of EventSubscriber\n */\n public static getInstance(): EventSubscriber {\n if (!EventSubscriber.instance) {\n EventSubscriber.instance = new EventSubscriber();\n }\n return EventSubscriber.instance;\n }\n\n /**\n * Register a tracking adapter\n * @param adapter The tracking adapter to register\n */\n public registerAdapter(adapter: TrackingAdapter): void {\n // Check if adapter with the same name already exists\n const existingAdapter = this.adapters.find((a) => a.name === adapter.name);\n if (existingAdapter) {\n console.warn(\n `Tracking adapter with name \"${adapter.name}\" is already registered. Skipping.`\n );\n return;\n }\n\n this.adapters.push(adapter);\n\n // If already initialized, initialize the new adapter\n if (this.initialized) {\n this.initializeAdapter(adapter).catch((error) => {\n console.error(`Failed to initialize adapter \"${adapter.name}\":`, error);\n });\n }\n }\n\n /**\n * Unregister a tracking adapter by name\n * @param adapterName The name of the adapter to unregister\n */\n public unregisterAdapter(adapterName: string): void {\n this.adapters = this.adapters.filter(\n (adapter) => adapter.name !== adapterName\n );\n }\n\n /**\n * Initialize all registered adapters\n */\n public async initialize(): Promise<void> {\n console.log(\"Initializing EventSubscriber...\");\n\n if (this.initialized) {\n console.log(\"EventSubscriber already initialized\");\n return;\n }\n\n // Subscribe to events\n this.unsubscribe = eventPublisher.subscribe(this.handleEvent.bind(this));\n console.log(\"Subscribed to event publisher\");\n\n // Initialize all adapters\n console.log(`Initializing ${this.adapters.length} adapters...`);\n await Promise.all(\n this.adapters.map((adapter) => this.initializeAdapter(adapter))\n );\n\n this.initialized = true;\n console.log(\"EventSubscriber initialization complete\");\n\n // Process any queued events\n this.processEventQueue();\n }\n\n /**\n * Initialize a single adapter\n * @param adapter The adapter to initialize\n */\n private async initializeAdapter(adapter: TrackingAdapter): Promise<void> {\n try {\n await adapter.initialize();\n console.log(\n `Tracking adapter \"${adapter.name}\" initialized successfully.`\n );\n } catch (error) {\n console.error(`Failed to initialize adapter \"${adapter.name}\":`, error);\n }\n }\n\n /**\n * Handle an event by forwarding it to all enabled adapters\n * @param event The event to handle\n * @param params Optional adapter-specific parameters\n */\n private handleEvent(event: TEvent, params?: TAdapterParams): void {\n console.log(\"Handling event:\", event.type, \"with params:\", params);\n\n if (!this.initialized) {\n console.log(\"Subscriber not initialized, queueing event\");\n this.eventQueue.push({ event, params });\n return;\n }\n\n // Forward the event to all enabled adapters\n for (const adapter of this.adapters) {\n if (adapter.isEnabled()) {\n console.log(`Forwarding event to adapter: ${adapter.name}`);\n adapter.trackEvent(event, params).catch((error) => {\n console.error(\n `Error tracking event in adapter \"${adapter.name}\":`,\n error\n );\n });\n } else {\n console.log(`Adapter ${adapter.name} is disabled, skipping`);\n }\n }\n }\n\n /**\n * Process any events that were queued before initialization\n */\n private processEventQueue(): void {\n if (this.eventQueue.length === 0) {\n return;\n }\n\n console.log(`Processing ${this.eventQueue.length} queued events.`);\n\n // Process each queued event\n for (const { event, params } of this.eventQueue) {\n this.handleEvent(event, params);\n }\n\n // Clear the queue\n this.eventQueue = [];\n }\n\n /**\n * Shutdown the subscriber and all adapters\n */\n public shutdown(): void {\n if (this.unsubscribe) {\n this.unsubscribe();\n this.unsubscribe = null;\n }\n\n this.initialized = false;\n this.eventQueue = [];\n }\n\n /**\n * Get all registered adapters\n */\n public getAdapters(): TrackingAdapter[] {\n return [...this.adapters];\n }\n}\n\n// Export singleton instance\nexport const eventSubscriber = EventSubscriber.getInstance();\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/services/facebook-capi.ts
|
|
4
|
+
var FacebookCAPIService = class {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
this.baseUrl = "https://graph.facebook.com/v18.0";
|
|
7
|
+
this.config = config;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Send events to Facebook CAPI
|
|
11
|
+
*/
|
|
12
|
+
async sendEvents(events, userInfo) {
|
|
13
|
+
if (!this.config.accessToken || !this.config.pixelId) {
|
|
14
|
+
console.warn("Facebook CAPI: Missing access token or pixel ID");
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const supportedEvents = events.filter(
|
|
18
|
+
(event) => this.isSupportedEvent(event.type)
|
|
19
|
+
);
|
|
20
|
+
if (supportedEvents.length === 0) {
|
|
21
|
+
console.log("Facebook CAPI: No supported events to send");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const capiEvents = supportedEvents.map(
|
|
25
|
+
(event) => this.convertToFacebookEvent(event, userInfo)
|
|
26
|
+
);
|
|
27
|
+
const payload = {
|
|
28
|
+
data: capiEvents,
|
|
29
|
+
test_event_code: this.config.testEventCode
|
|
30
|
+
};
|
|
31
|
+
try {
|
|
32
|
+
const response = await fetch(
|
|
33
|
+
`${this.baseUrl}/${this.config.pixelId}/events?access_token=${this.config.accessToken}`,
|
|
34
|
+
{
|
|
35
|
+
method: "POST",
|
|
36
|
+
headers: {
|
|
37
|
+
"Content-Type": "application/json"
|
|
38
|
+
},
|
|
39
|
+
body: JSON.stringify(payload)
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
const errorData = await response.json();
|
|
44
|
+
console.error("Facebook CAPI Error:", errorData);
|
|
45
|
+
throw new Error(`Facebook CAPI request failed: ${response.status}`);
|
|
46
|
+
}
|
|
47
|
+
const result = await response.json();
|
|
48
|
+
console.log("Facebook CAPI: Events sent successfully", {
|
|
49
|
+
events_received: result.events_received,
|
|
50
|
+
messages: result.messages
|
|
51
|
+
});
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error("Facebook CAPI: Failed to send events", error);
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Check if event type is supported (matches PixelAdapter implementation)
|
|
59
|
+
*/
|
|
60
|
+
isSupportedEvent(eventType) {
|
|
61
|
+
return [
|
|
62
|
+
"page_view" /* PAGE_VIEW */,
|
|
63
|
+
"product_view" /* PRODUCT_VIEW */,
|
|
64
|
+
"add_to_cart" /* ADD_TO_CART */,
|
|
65
|
+
"search" /* SEARCH */
|
|
66
|
+
].includes(eventType);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Convert internal event to Facebook CAPI event format
|
|
70
|
+
* Only handles events implemented in PixelAdapter
|
|
71
|
+
*/
|
|
72
|
+
convertToFacebookEvent(event, userInfo) {
|
|
73
|
+
const baseEvent = {
|
|
74
|
+
event_name: this.mapEventName(event.type),
|
|
75
|
+
event_time: Math.floor((event.timestamp || Date.now()) / 1e3),
|
|
76
|
+
event_id: event.eventId,
|
|
77
|
+
action_source: "website",
|
|
78
|
+
user_data: userInfo ? {
|
|
79
|
+
client_ip_address: userInfo.clientIpAddress,
|
|
80
|
+
client_user_agent: userInfo.clientUserAgent,
|
|
81
|
+
fbc: userInfo.fbc,
|
|
82
|
+
fbp: userInfo.fbp
|
|
83
|
+
} : void 0
|
|
84
|
+
};
|
|
85
|
+
switch (event.type) {
|
|
86
|
+
case "page_view" /* PAGE_VIEW */:
|
|
87
|
+
baseEvent.custom_data = {};
|
|
88
|
+
break;
|
|
89
|
+
case "product_view" /* PRODUCT_VIEW */:
|
|
90
|
+
const productEvent = event;
|
|
91
|
+
baseEvent.custom_data = {
|
|
92
|
+
content_type: "product_group",
|
|
93
|
+
content_ids: [productEvent.productId],
|
|
94
|
+
content_name: productEvent.productName,
|
|
95
|
+
content_category: productEvent.event_category,
|
|
96
|
+
value: productEvent.price,
|
|
97
|
+
currency: productEvent.currency || "INR"
|
|
98
|
+
};
|
|
99
|
+
break;
|
|
100
|
+
case "add_to_cart" /* ADD_TO_CART */:
|
|
101
|
+
const cartEvent = event;
|
|
102
|
+
baseEvent.custom_data = {
|
|
103
|
+
content_type: "product_group",
|
|
104
|
+
content_ids: [cartEvent.productId],
|
|
105
|
+
content_name: cartEvent.productName,
|
|
106
|
+
value: cartEvent.price,
|
|
107
|
+
currency: cartEvent.currency || "INR"
|
|
108
|
+
};
|
|
109
|
+
break;
|
|
110
|
+
case "search" /* SEARCH */:
|
|
111
|
+
const searchEvent = event;
|
|
112
|
+
baseEvent.custom_data = {
|
|
113
|
+
search_string: searchEvent.searchTerm,
|
|
114
|
+
content_category: "product",
|
|
115
|
+
content_ids: searchEvent.content_ids || []
|
|
116
|
+
};
|
|
117
|
+
break;
|
|
118
|
+
default:
|
|
119
|
+
baseEvent.custom_data = {};
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
return baseEvent;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Map internal event types to Facebook event names (matching PixelAdapter)
|
|
126
|
+
*/
|
|
127
|
+
mapEventName(eventType) {
|
|
128
|
+
const eventMap = {
|
|
129
|
+
["page_view" /* PAGE_VIEW */]: "PageView",
|
|
130
|
+
["product_view" /* PRODUCT_VIEW */]: "ViewContent",
|
|
131
|
+
["add_to_cart" /* ADD_TO_CART */]: "AddToCart",
|
|
132
|
+
["search" /* SEARCH */]: "Search"
|
|
133
|
+
};
|
|
134
|
+
return eventMap[eventType] || "CustomEvent";
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
function createFacebookCAPIService(config) {
|
|
138
|
+
const accessToken = config?.accessToken || process.env.FACEBOOK_CAPI_ACCESS_TOKEN;
|
|
139
|
+
const pixelId = config?.pixelId || process.env.NEXT_PUBLIC_PIXEL_ID;
|
|
140
|
+
const testEventCode = config?.testEventCode || process.env.FACEBOOK_TEST_EVENT_CODE;
|
|
141
|
+
if (!accessToken || !pixelId) {
|
|
142
|
+
console.warn("Facebook CAPI: Missing access token or pixel ID");
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
return new FacebookCAPIService({
|
|
146
|
+
accessToken,
|
|
147
|
+
pixelId,
|
|
148
|
+
testEventCode
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export {
|
|
153
|
+
FacebookCAPIService,
|
|
154
|
+
createFacebookCAPIService
|
|
155
|
+
};
|
|
156
|
+
//# sourceMappingURL=chunk-NC25KOAF.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/facebook-capi.ts"],"sourcesContent":["import {\n TEvent,\n EventType,\n type IAddToCartEvent,\n type IProductViewEvent,\n type ISearchEvent,\n} from \"../types\";\n\n/**\n * Facebook CAPI Configuration\n */\nexport interface FacebookCAPIConfig {\n accessToken: string;\n pixelId: string;\n testEventCode?: string;\n}\n\n/**\n * Facebook CAPI Event Data Structure\n */\ninterface FacebookCAPIEvent {\n event_name: string;\n event_time: number;\n event_id?: string;\n user_data?: {\n client_ip_address?: string;\n client_user_agent?: string;\n fbc?: string;\n fbp?: string;\n };\n custom_data?: {\n currency?: string;\n value?: number;\n content_ids?: string[];\n content_type?: string;\n content_name?: string;\n content_category?: string;\n search_string?: string;\n [key: string]: any;\n };\n action_source: string;\n}\n\n/**\n * Facebook CAPI Service for server-side event tracking\n * Only handles events that are implemented in PixelAdapter\n */\nexport class FacebookCAPIService {\n private config: FacebookCAPIConfig;\n private baseUrl = \"https://graph.facebook.com/v18.0\";\n\n constructor(config: FacebookCAPIConfig) {\n this.config = config;\n }\n\n /**\n * Send events to Facebook CAPI\n */\n public async sendEvents(\n events: TEvent[],\n userInfo?: {\n clientIpAddress?: string;\n clientUserAgent?: string;\n fbc?: string;\n fbp?: string;\n }\n ): Promise<void> {\n if (!this.config.accessToken || !this.config.pixelId) {\n console.warn(\"Facebook CAPI: Missing access token or pixel ID\");\n return;\n }\n\n // Filter events to only supported ones\n const supportedEvents = events.filter((event) =>\n this.isSupportedEvent(event.type)\n );\n\n if (supportedEvents.length === 0) {\n console.log(\"Facebook CAPI: No supported events to send\");\n return;\n }\n\n const capiEvents = supportedEvents.map((event) =>\n this.convertToFacebookEvent(event, userInfo)\n );\n\n const payload = {\n data: capiEvents,\n test_event_code: this.config.testEventCode,\n };\n\n try {\n const response = await fetch(\n `${this.baseUrl}/${this.config.pixelId}/events?access_token=${this.config.accessToken}`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(payload),\n }\n );\n\n if (!response.ok) {\n const errorData = await response.json();\n console.error(\"Facebook CAPI Error:\", errorData);\n throw new Error(`Facebook CAPI request failed: ${response.status}`);\n }\n\n const result = await response.json();\n console.log(\"Facebook CAPI: Events sent successfully\", {\n events_received: result.events_received,\n messages: result.messages,\n });\n } catch (error) {\n console.error(\"Facebook CAPI: Failed to send events\", error);\n throw error;\n }\n }\n\n /**\n * Check if event type is supported (matches PixelAdapter implementation)\n */\n private isSupportedEvent(eventType: EventType): boolean {\n return [\n EventType.PAGE_VIEW,\n EventType.PRODUCT_VIEW,\n EventType.ADD_TO_CART,\n EventType.SEARCH,\n ].includes(eventType);\n }\n\n /**\n * Convert internal event to Facebook CAPI event format\n * Only handles events implemented in PixelAdapter\n */\n private convertToFacebookEvent(\n event: TEvent,\n userInfo?: {\n clientIpAddress?: string;\n clientUserAgent?: string;\n fbc?: string;\n fbp?: string;\n }\n ): FacebookCAPIEvent {\n const baseEvent: FacebookCAPIEvent = {\n event_name: this.mapEventName(event.type),\n event_time: Math.floor((event.timestamp || Date.now()) / 1000),\n event_id: event.eventId,\n action_source: \"website\",\n user_data: userInfo\n ? {\n client_ip_address: userInfo.clientIpAddress,\n client_user_agent: userInfo.clientUserAgent,\n fbc: userInfo.fbc,\n fbp: userInfo.fbp,\n }\n : undefined,\n };\n\n // Add custom data based on event type (matching PixelAdapter logic)\n switch (event.type) {\n case EventType.PAGE_VIEW:\n baseEvent.custom_data = {};\n break;\n\n case EventType.PRODUCT_VIEW:\n const productEvent = event as IProductViewEvent;\n baseEvent.custom_data = {\n content_type: \"product_group\",\n content_ids: [productEvent.productId],\n content_name: productEvent.productName,\n content_category: productEvent.event_category,\n value: productEvent.price,\n currency: productEvent.currency || \"INR\",\n };\n break;\n\n case EventType.ADD_TO_CART:\n const cartEvent = event as IAddToCartEvent;\n baseEvent.custom_data = {\n content_type: \"product_group\",\n content_ids: [cartEvent.productId],\n content_name: cartEvent.productName,\n value: cartEvent.price,\n currency: cartEvent.currency || \"INR\",\n };\n break;\n\n case EventType.SEARCH:\n const searchEvent = event as ISearchEvent;\n baseEvent.custom_data = {\n search_string: searchEvent.searchTerm,\n content_category: \"product\",\n content_ids: searchEvent.content_ids || [],\n };\n break;\n\n default:\n baseEvent.custom_data = {};\n break;\n }\n\n return baseEvent;\n }\n\n /**\n * Map internal event types to Facebook event names (matching PixelAdapter)\n */\n private mapEventName(eventType: EventType): string {\n const eventMap: Record<EventType, string> = {\n [EventType.PAGE_VIEW]: \"PageView\",\n [EventType.PRODUCT_VIEW]: \"ViewContent\",\n [EventType.ADD_TO_CART]: \"AddToCart\",\n [EventType.SEARCH]: \"Search\",\n } as Record<EventType, string>;\n\n return eventMap[eventType] || \"CustomEvent\";\n }\n}\n\n/**\n * Create Facebook CAPI service instance\n */\nexport function createFacebookCAPIService(config?: {\n accessToken: string;\n pixelId: string;\n testEventCode?: string;\n}): FacebookCAPIService | null {\n const accessToken =\n config?.accessToken || process.env.FACEBOOK_CAPI_ACCESS_TOKEN;\n const pixelId = config?.pixelId || process.env.NEXT_PUBLIC_PIXEL_ID;\n const testEventCode =\n config?.testEventCode || process.env.FACEBOOK_TEST_EVENT_CODE;\n\n if (!accessToken || !pixelId) {\n console.warn(\"Facebook CAPI: Missing access token or pixel ID\");\n return null;\n }\n\n return new FacebookCAPIService({\n accessToken,\n pixelId,\n testEventCode,\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/experiment/constants.ts
|
|
4
|
+
var PRIMA_EXPERIMENT_COOKIES = {
|
|
5
|
+
HOME: "_prima_pr_ab_home",
|
|
6
|
+
COLLECTION: "_prima_pr_ab_collection",
|
|
7
|
+
PRODUCT: "_prima_pr_ab_product"
|
|
8
|
+
};
|
|
9
|
+
var PRIMA_EXPERIMENT_COOKIE_NAMES = Object.values(
|
|
10
|
+
PRIMA_EXPERIMENT_COOKIES
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
// src/experiment/experiment-tracker.ts
|
|
14
|
+
function getCookie(name) {
|
|
15
|
+
if (typeof document === "undefined") return null;
|
|
16
|
+
const value = `; ${document.cookie}`;
|
|
17
|
+
const parts = value.split(`; ${name}=`);
|
|
18
|
+
if (parts.length === 2) {
|
|
19
|
+
return parts.pop()?.split(";").shift() || null;
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
function getExperimentParams() {
|
|
24
|
+
return {
|
|
25
|
+
[PRIMA_EXPERIMENT_COOKIES.HOME]: getCookie(PRIMA_EXPERIMENT_COOKIES.HOME),
|
|
26
|
+
[PRIMA_EXPERIMENT_COOKIES.COLLECTION]: getCookie(
|
|
27
|
+
PRIMA_EXPERIMENT_COOKIES.COLLECTION
|
|
28
|
+
),
|
|
29
|
+
[PRIMA_EXPERIMENT_COOKIES.PRODUCT]: getCookie(
|
|
30
|
+
PRIMA_EXPERIMENT_COOKIES.PRODUCT
|
|
31
|
+
)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function hasExperimentData() {
|
|
35
|
+
return PRIMA_EXPERIMENT_COOKIE_NAMES.some(
|
|
36
|
+
(cookieName) => getCookie(cookieName) !== null
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
PRIMA_EXPERIMENT_COOKIES,
|
|
42
|
+
PRIMA_EXPERIMENT_COOKIE_NAMES,
|
|
43
|
+
getExperimentParams,
|
|
44
|
+
hasExperimentData
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=chunk-NGPUKV7E.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/experiment/constants.ts","../src/experiment/experiment-tracker.ts"],"sourcesContent":["/**\n * Prima PR A/B test experiment cookie names\n */\nexport const PRIMA_EXPERIMENT_COOKIES = {\n HOME: \"_prima_pr_ab_home\",\n COLLECTION: \"_prima_pr_ab_collection\",\n PRODUCT: \"_prima_pr_ab_product\",\n} as const;\n\n/**\n * Array of all Prima experiment cookie names for iteration\n */\nexport const PRIMA_EXPERIMENT_COOKIE_NAMES = Object.values(\n PRIMA_EXPERIMENT_COOKIES\n);\n","import type { ExperimentData } from \"./types\";\nimport {\n PRIMA_EXPERIMENT_COOKIES,\n PRIMA_EXPERIMENT_COOKIE_NAMES,\n} from \"./constants\";\n\n/**\n * Get cookie value by name\n */\nfunction getCookie(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n\n const value = `; ${document.cookie}`;\n const parts = value.split(`; ${name}=`);\n if (parts.length === 2) {\n return parts.pop()?.split(\";\").shift() || null;\n }\n return null;\n}\n\n/**\n * Get experiment parameters from cookies\n */\nexport function getExperimentParams(): ExperimentData {\n return {\n [PRIMA_EXPERIMENT_COOKIES.HOME]: getCookie(PRIMA_EXPERIMENT_COOKIES.HOME),\n [PRIMA_EXPERIMENT_COOKIES.COLLECTION]: getCookie(\n PRIMA_EXPERIMENT_COOKIES.COLLECTION\n ),\n [PRIMA_EXPERIMENT_COOKIES.PRODUCT]: getCookie(\n PRIMA_EXPERIMENT_COOKIES.PRODUCT\n ),\n };\n}\n\n/**\n * Check if any experiment data exists\n */\nexport function hasExperimentData(): boolean {\n return PRIMA_EXPERIMENT_COOKIE_NAMES.some(\n (cookieName) => getCookie(cookieName) !== null\n );\n}\n"],"mappings":";;;AAGO,IAAM,2BAA2B;AAAA,EACtC,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,SAAS;AACX;AAKO,IAAM,gCAAgC,OAAO;AAAA,EAClD;AACF;;;ACLA,SAAS,UAAU,MAA6B;AAC9C,MAAI,OAAO,aAAa,YAAa,QAAO;AAE5C,QAAM,QAAQ,KAAK,SAAS,MAAM;AAClC,QAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,GAAG;AACtC,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,MAAM,IAAI,GAAG,MAAM,GAAG,EAAE,MAAM,KAAK;AAAA,EAC5C;AACA,SAAO;AACT;AAKO,SAAS,sBAAsC;AACpD,SAAO;AAAA,IACL,CAAC,yBAAyB,IAAI,GAAG,UAAU,yBAAyB,IAAI;AAAA,IACxE,CAAC,yBAAyB,UAAU,GAAG;AAAA,MACrC,yBAAyB;AAAA,IAC3B;AAAA,IACA,CAAC,yBAAyB,OAAO,GAAG;AAAA,MAClC,yBAAyB;AAAA,IAC3B;AAAA,EACF;AACF;AAKO,SAAS,oBAA6B;AAC3C,SAAO,8BAA8B;AAAA,IACnC,CAAC,eAAe,UAAU,UAAU,MAAM;AAAA,EAC5C;AACF;","names":[]}
|