@od-oneapp/analytics 2026.1.1301

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.
Files changed (184) hide show
  1. package/README.md +509 -0
  2. package/dist/ai-YMnynb-t.mjs +3347 -0
  3. package/dist/ai-YMnynb-t.mjs.map +1 -0
  4. package/dist/chunk-DQk6qfdC.mjs +18 -0
  5. package/dist/client-CTzJVFU5.mjs +9 -0
  6. package/dist/client-CTzJVFU5.mjs.map +1 -0
  7. package/dist/client-CcFTauAh.mjs +54 -0
  8. package/dist/client-CcFTauAh.mjs.map +1 -0
  9. package/dist/client-CeOLjbac.mjs +281 -0
  10. package/dist/client-CeOLjbac.mjs.map +1 -0
  11. package/dist/client-D339NFJS.mjs +267 -0
  12. package/dist/client-D339NFJS.mjs.map +1 -0
  13. package/dist/client-next.d.mts +62 -0
  14. package/dist/client-next.d.mts.map +1 -0
  15. package/dist/client-next.mjs +525 -0
  16. package/dist/client-next.mjs.map +1 -0
  17. package/dist/client.d.mts +30 -0
  18. package/dist/client.d.mts.map +1 -0
  19. package/dist/client.mjs +186 -0
  20. package/dist/client.mjs.map +1 -0
  21. package/dist/config-DPS6bSYo.d.mts +34 -0
  22. package/dist/config-DPS6bSYo.d.mts.map +1 -0
  23. package/dist/config-P6P5adJg.mjs +287 -0
  24. package/dist/config-P6P5adJg.mjs.map +1 -0
  25. package/dist/console-8bND3mMU.mjs +128 -0
  26. package/dist/console-8bND3mMU.mjs.map +1 -0
  27. package/dist/ecommerce-Cgu4wlux.mjs +993 -0
  28. package/dist/ecommerce-Cgu4wlux.mjs.map +1 -0
  29. package/dist/emitters-6-nKo8i-.mjs +208 -0
  30. package/dist/emitters-6-nKo8i-.mjs.map +1 -0
  31. package/dist/emitters-DldkVSPp.d.mts +12 -0
  32. package/dist/emitters-DldkVSPp.d.mts.map +1 -0
  33. package/dist/index-BfNWgfa5.d.mts +1494 -0
  34. package/dist/index-BfNWgfa5.d.mts.map +1 -0
  35. package/dist/index-BkIWe--N.d.mts +953 -0
  36. package/dist/index-BkIWe--N.d.mts.map +1 -0
  37. package/dist/index-jPzXRn52.d.mts +184 -0
  38. package/dist/index-jPzXRn52.d.mts.map +1 -0
  39. package/dist/manager-DvRRjza6.d.mts +76 -0
  40. package/dist/manager-DvRRjza6.d.mts.map +1 -0
  41. package/dist/posthog-bootstrap-CYfIy_WS.mjs +1769 -0
  42. package/dist/posthog-bootstrap-CYfIy_WS.mjs.map +1 -0
  43. package/dist/posthog-bootstrap-DWxFrxlt.d.mts +81 -0
  44. package/dist/posthog-bootstrap-DWxFrxlt.d.mts.map +1 -0
  45. package/dist/providers-http-client.d.mts +37 -0
  46. package/dist/providers-http-client.d.mts.map +1 -0
  47. package/dist/providers-http-client.mjs +320 -0
  48. package/dist/providers-http-client.mjs.map +1 -0
  49. package/dist/providers-http-server.d.mts +31 -0
  50. package/dist/providers-http-server.d.mts.map +1 -0
  51. package/dist/providers-http-server.mjs +297 -0
  52. package/dist/providers-http-server.mjs.map +1 -0
  53. package/dist/providers-http.d.mts +46 -0
  54. package/dist/providers-http.d.mts.map +1 -0
  55. package/dist/providers-http.mjs +4 -0
  56. package/dist/server-edge.d.mts +9 -0
  57. package/dist/server-edge.d.mts.map +1 -0
  58. package/dist/server-edge.mjs +373 -0
  59. package/dist/server-edge.mjs.map +1 -0
  60. package/dist/server-next.d.mts +67 -0
  61. package/dist/server-next.d.mts.map +1 -0
  62. package/dist/server-next.mjs +193 -0
  63. package/dist/server-next.mjs.map +1 -0
  64. package/dist/server.d.mts +10 -0
  65. package/dist/server.mjs +7 -0
  66. package/dist/service-cYtBBL8x.mjs +945 -0
  67. package/dist/service-cYtBBL8x.mjs.map +1 -0
  68. package/dist/shared.d.mts +16 -0
  69. package/dist/shared.d.mts.map +1 -0
  70. package/dist/shared.mjs +93 -0
  71. package/dist/shared.mjs.map +1 -0
  72. package/dist/types-BxBnNQ0V.d.mts +354 -0
  73. package/dist/types-BxBnNQ0V.d.mts.map +1 -0
  74. package/dist/types-CBvxUEaF.d.mts +216 -0
  75. package/dist/types-CBvxUEaF.d.mts.map +1 -0
  76. package/dist/types.d.mts +4 -0
  77. package/dist/types.mjs +0 -0
  78. package/dist/vercel-types-lwakUfoI.d.mts +102 -0
  79. package/dist/vercel-types-lwakUfoI.d.mts.map +1 -0
  80. package/package.json +129 -0
  81. package/src/client/index.ts +164 -0
  82. package/src/client/manager.ts +71 -0
  83. package/src/client/next/components.tsx +270 -0
  84. package/src/client/next/hooks.ts +217 -0
  85. package/src/client/next/manager.ts +141 -0
  86. package/src/client/next.ts +144 -0
  87. package/src/client-next.ts +101 -0
  88. package/src/client.ts +89 -0
  89. package/src/examples/ai-sdk-patterns.ts +583 -0
  90. package/src/examples/emitter-patterns.ts +476 -0
  91. package/src/examples/nextjs-emitter-patterns.tsx +403 -0
  92. package/src/next/app-router.tsx +564 -0
  93. package/src/next/client.ts +419 -0
  94. package/src/next/index.ts +84 -0
  95. package/src/next/middleware.ts +429 -0
  96. package/src/next/rsc.tsx +300 -0
  97. package/src/next/server.ts +253 -0
  98. package/src/next/types.d.ts +220 -0
  99. package/src/providers/base-provider.ts +419 -0
  100. package/src/providers/console/client.ts +10 -0
  101. package/src/providers/console/index.ts +152 -0
  102. package/src/providers/console/server.ts +6 -0
  103. package/src/providers/console/types.ts +15 -0
  104. package/src/providers/http/client.ts +464 -0
  105. package/src/providers/http/index.ts +30 -0
  106. package/src/providers/http/server.ts +396 -0
  107. package/src/providers/http/types.ts +135 -0
  108. package/src/providers/posthog/client.ts +518 -0
  109. package/src/providers/posthog/index.ts +11 -0
  110. package/src/providers/posthog/server.ts +329 -0
  111. package/src/providers/posthog/types.ts +104 -0
  112. package/src/providers/segment/client.ts +113 -0
  113. package/src/providers/segment/index.ts +11 -0
  114. package/src/providers/segment/server.ts +115 -0
  115. package/src/providers/segment/types.ts +51 -0
  116. package/src/providers/vercel/client.ts +102 -0
  117. package/src/providers/vercel/index.ts +11 -0
  118. package/src/providers/vercel/server.ts +89 -0
  119. package/src/providers/vercel/types.ts +27 -0
  120. package/src/server/index.ts +103 -0
  121. package/src/server/manager.ts +62 -0
  122. package/src/server/next.ts +210 -0
  123. package/src/server-edge.ts +442 -0
  124. package/src/server-next.ts +39 -0
  125. package/src/server.ts +106 -0
  126. package/src/shared/emitters/ai/README.md +981 -0
  127. package/src/shared/emitters/ai/events/agent.ts +130 -0
  128. package/src/shared/emitters/ai/events/artifacts.ts +167 -0
  129. package/src/shared/emitters/ai/events/chat.ts +126 -0
  130. package/src/shared/emitters/ai/events/chatbot-ecommerce.ts +133 -0
  131. package/src/shared/emitters/ai/events/completion.ts +103 -0
  132. package/src/shared/emitters/ai/events/content-generation.ts +347 -0
  133. package/src/shared/emitters/ai/events/conversation.ts +332 -0
  134. package/src/shared/emitters/ai/events/product-features.ts +1402 -0
  135. package/src/shared/emitters/ai/events/streaming.ts +114 -0
  136. package/src/shared/emitters/ai/events/tool.ts +93 -0
  137. package/src/shared/emitters/ai/index.ts +69 -0
  138. package/src/shared/emitters/ai/track-ai-sdk.ts +74 -0
  139. package/src/shared/emitters/ai/track-ai.ts +50 -0
  140. package/src/shared/emitters/ai/types.ts +1041 -0
  141. package/src/shared/emitters/ai/utils.ts +468 -0
  142. package/src/shared/emitters/ecommerce/events/cart-checkout.ts +106 -0
  143. package/src/shared/emitters/ecommerce/events/coupon.ts +49 -0
  144. package/src/shared/emitters/ecommerce/events/engagement.ts +61 -0
  145. package/src/shared/emitters/ecommerce/events/marketplace.ts +119 -0
  146. package/src/shared/emitters/ecommerce/events/order.ts +199 -0
  147. package/src/shared/emitters/ecommerce/events/product.ts +205 -0
  148. package/src/shared/emitters/ecommerce/events/registry.ts +123 -0
  149. package/src/shared/emitters/ecommerce/events/wishlist-sharing.ts +140 -0
  150. package/src/shared/emitters/ecommerce/index.ts +46 -0
  151. package/src/shared/emitters/ecommerce/track-ecommerce.ts +53 -0
  152. package/src/shared/emitters/ecommerce/types.ts +314 -0
  153. package/src/shared/emitters/ecommerce/utils.ts +216 -0
  154. package/src/shared/emitters/emitter-types.ts +974 -0
  155. package/src/shared/emitters/emitters.ts +292 -0
  156. package/src/shared/emitters/helpers.ts +419 -0
  157. package/src/shared/emitters/index.ts +66 -0
  158. package/src/shared/index.ts +142 -0
  159. package/src/shared/ingestion/index.ts +66 -0
  160. package/src/shared/ingestion/schemas.ts +386 -0
  161. package/src/shared/ingestion/service.ts +628 -0
  162. package/src/shared/node22-features.ts +848 -0
  163. package/src/shared/providers/console-provider.ts +160 -0
  164. package/src/shared/types/base-types.ts +54 -0
  165. package/src/shared/types/console-types.ts +19 -0
  166. package/src/shared/types/posthog-types.ts +131 -0
  167. package/src/shared/types/segment-types.ts +15 -0
  168. package/src/shared/types/types.ts +397 -0
  169. package/src/shared/types/vercel-types.ts +19 -0
  170. package/src/shared/utils/config-client.ts +19 -0
  171. package/src/shared/utils/config.ts +250 -0
  172. package/src/shared/utils/emitter-adapter.ts +212 -0
  173. package/src/shared/utils/manager.test.ts +36 -0
  174. package/src/shared/utils/manager.ts +1322 -0
  175. package/src/shared/utils/posthog-bootstrap.ts +136 -0
  176. package/src/shared/utils/posthog-client-utils.ts +48 -0
  177. package/src/shared/utils/posthog-next-utils.ts +282 -0
  178. package/src/shared/utils/posthog-server-utils.ts +210 -0
  179. package/src/shared/utils/rate-limit.ts +289 -0
  180. package/src/shared/utils/security.ts +545 -0
  181. package/src/shared/utils/validation-client.ts +161 -0
  182. package/src/shared/utils/validation.ts +399 -0
  183. package/src/shared.ts +155 -0
  184. package/src/types/index.ts +62 -0
@@ -0,0 +1,119 @@
1
+ /**
2
+ * @fileoverview Marketplace and affiliate-specific ecommerce events
3
+ * Marketplace and affiliate-specific ecommerce events
4
+ * These events track user interactions unique to marketplace/affiliate models
5
+ */
6
+
7
+ import { type BaseProductProperties, ECOMMERCE_EVENTS, type EcommerceEventSpec } from '../types';
8
+ import { cleanProperties, normalizeProductProperties, validateRequiredProperties } from '../utils';
9
+
10
+ /**
11
+ * Track when a user views price comparisons across multiple merchants
12
+ */
13
+ export function priceComparisonViewed(properties: {
14
+ product_id: string;
15
+ merchants: {
16
+ merchant_id: string;
17
+ merchant_name: string;
18
+ price: number;
19
+ shipping?: number;
20
+ total_price?: number;
21
+ availability?: string;
22
+ rating?: number;
23
+ }[];
24
+ lowest_price?: number;
25
+ highest_price?: number;
26
+ average_price?: number;
27
+ }): EcommerceEventSpec {
28
+ validateRequiredProperties(properties, ['product_id', 'merchants']);
29
+
30
+ return {
31
+ name: ECOMMERCE_EVENTS.PRICE_COMPARISON_VIEWED,
32
+ category: 'ecommerce',
33
+ properties: cleanProperties(properties),
34
+ requiredProperties: ['product_id', 'merchants'],
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Track when a user selects a specific merchant from multiple options
40
+ */
41
+ export function merchantSelected(
42
+ properties: BaseProductProperties & {
43
+ selected_merchant_id: string;
44
+ selected_merchant_name: string;
45
+ selection_reason?: 'lowest_price' | 'fastest_shipping' | 'best_rating' | 'in_stock' | 'other';
46
+ compared_merchants?: string[];
47
+ },
48
+ ): EcommerceEventSpec {
49
+ const normalizedProps = normalizeProductProperties(properties);
50
+ validateRequiredProperties(properties, ['product_id', 'selected_merchant_id']);
51
+
52
+ return {
53
+ name: ECOMMERCE_EVENTS.MERCHANT_SELECTED,
54
+ category: 'ecommerce',
55
+ properties: cleanProperties({
56
+ ...normalizedProps,
57
+ selected_merchant_id: properties.selected_merchant_id,
58
+ selected_merchant_name: properties.selected_merchant_name,
59
+ compared_merchants: properties.compared_merchants,
60
+ selection_reason: properties.selection_reason,
61
+ }),
62
+ requiredProperties: ['product_id', 'selected_merchant_id'],
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Track when a user clicks an affiliate link to visit merchant site
68
+ */
69
+ export function affiliateLinkClicked(
70
+ properties: BaseProductProperties & {
71
+ destination_url: string;
72
+ affiliate_network?: string;
73
+ commission_rate?: number;
74
+ tracking_code?: string;
75
+ deep_link?: boolean;
76
+ },
77
+ ): EcommerceEventSpec {
78
+ const normalizedProps = normalizeProductProperties(properties);
79
+ validateRequiredProperties(properties, ['product_id', 'destination_url']);
80
+
81
+ return {
82
+ name: ECOMMERCE_EVENTS.AFFILIATE_LINK_CLICKED,
83
+ category: 'ecommerce',
84
+ properties: cleanProperties({
85
+ ...normalizedProps,
86
+ destination_url: properties.destination_url,
87
+ deep_link: properties.deep_link,
88
+ tracking_code: properties.tracking_code,
89
+ }),
90
+ requiredProperties: ['product_id', 'destination_url'],
91
+ };
92
+ }
93
+
94
+ /**
95
+ * Track when an affiliate conversion is confirmed
96
+ * This is typically fired via webhook or after confirmation from affiliate network
97
+ */
98
+ export function affiliateConversionTracked(properties: {
99
+ product_id: string;
100
+ order_id: string;
101
+ merchant_id: string;
102
+ merchant_name?: string;
103
+ affiliate_network?: string;
104
+ commission_amount?: number;
105
+ commission_rate?: number;
106
+ conversion_value?: number;
107
+ currency?: string;
108
+ conversion_type?: 'sale' | 'lead' | 'click' | 'other';
109
+ tracking_code?: string;
110
+ }): EcommerceEventSpec {
111
+ validateRequiredProperties(properties, ['product_id', 'order_id', 'merchant_id']);
112
+
113
+ return {
114
+ name: ECOMMERCE_EVENTS.AFFILIATE_CONVERSION_TRACKED,
115
+ category: 'ecommerce',
116
+ properties: cleanProperties(properties),
117
+ requiredProperties: ['product_id', 'order_id', 'merchant_id'],
118
+ };
119
+ }
@@ -0,0 +1,199 @@
1
+ /**
2
+ * @fileoverview Order-related ecommerce events
3
+ * Order-related ecommerce events
4
+ */
5
+
6
+ import { trackEcommerce } from '../track-ecommerce';
7
+ import {
8
+ ECOMMERCE_EVENTS,
9
+ type EcommerceEventSpec,
10
+ type OrderProperties,
11
+ type OrderStatusProperties,
12
+ type ReturnProperties,
13
+ } from '../types';
14
+ import {
15
+ cleanProperties,
16
+ normalizeProducts,
17
+ validateCurrency,
18
+ validateRequiredProperties,
19
+ } from '../utils';
20
+
21
+ import type { EmitterOptions, EmitterTrackPayload } from '../../emitter-types';
22
+
23
+ /**
24
+ * Track when a user completes an order
25
+ */
26
+ export function orderCompleted(
27
+ properties: OrderProperties,
28
+ options?: EmitterOptions,
29
+ ): EmitterTrackPayload {
30
+ validateRequiredProperties(properties, ['order_id']);
31
+
32
+ const normalizedProps: OrderProperties = {
33
+ order_id: properties.order_id,
34
+ affiliation: properties.affiliation,
35
+ coupon: properties.coupon,
36
+ currency: validateCurrency(properties.currency),
37
+ discount: properties.discount,
38
+ products: properties.products ? normalizeProducts(properties.products) : undefined,
39
+ revenue: properties.revenue,
40
+ shipping: properties.shipping,
41
+ tax: properties.tax,
42
+ total: properties.total,
43
+ };
44
+
45
+ const eventSpec: EcommerceEventSpec = {
46
+ name: ECOMMERCE_EVENTS.ORDER_COMPLETED,
47
+ category: 'ecommerce',
48
+ properties: cleanProperties(normalizedProps),
49
+ requiredProperties: ['order_id'],
50
+ };
51
+
52
+ return trackEcommerce(eventSpec, options);
53
+ }
54
+
55
+ /**
56
+ * Track when an order fails (payment declined, validation error, etc.)
57
+ */
58
+ export function orderFailed(
59
+ properties: OrderProperties & {
60
+ failure_reason?: string;
61
+ error_code?: string;
62
+ },
63
+ ): EcommerceEventSpec {
64
+ validateRequiredProperties(properties, ['order_id']);
65
+
66
+ const { error_code, failure_reason, ...orderProps } = properties;
67
+ const normalizedProps = {
68
+ order_id: orderProps.order_id,
69
+ affiliation: orderProps.affiliation,
70
+ coupon: orderProps.coupon,
71
+ currency: validateCurrency(orderProps.currency),
72
+ discount: orderProps.discount,
73
+ error_code,
74
+ failure_reason,
75
+ products: orderProps.products ? normalizeProducts(orderProps.products) : undefined,
76
+ revenue: orderProps.revenue,
77
+ shipping: orderProps.shipping,
78
+ tax: orderProps.tax,
79
+ total: orderProps.total,
80
+ };
81
+
82
+ return {
83
+ name: ECOMMERCE_EVENTS.ORDER_FAILED,
84
+ category: 'ecommerce',
85
+ properties: cleanProperties(normalizedProps),
86
+ requiredProperties: ['order_id'],
87
+ };
88
+ }
89
+
90
+ /**
91
+ * Track when an order is refunded
92
+ */
93
+ export function orderRefunded(properties: OrderProperties): EcommerceEventSpec {
94
+ validateRequiredProperties(properties, ['order_id']);
95
+
96
+ const normalizedProps: OrderProperties = {
97
+ order_id: properties.order_id,
98
+ affiliation: properties.affiliation,
99
+ coupon: properties.coupon,
100
+ currency: validateCurrency(properties.currency),
101
+ discount: properties.discount,
102
+ products: properties.products ? normalizeProducts(properties.products) : undefined,
103
+ revenue: properties.revenue,
104
+ shipping: properties.shipping,
105
+ tax: properties.tax,
106
+ total: properties.total,
107
+ };
108
+
109
+ return {
110
+ name: ECOMMERCE_EVENTS.ORDER_REFUNDED,
111
+ category: 'ecommerce',
112
+ properties: cleanProperties(normalizedProps),
113
+ requiredProperties: ['order_id'],
114
+ };
115
+ }
116
+
117
+ /**
118
+ * Track when an order is cancelled
119
+ */
120
+ export function orderCancelled(properties: OrderProperties): EcommerceEventSpec {
121
+ validateRequiredProperties(properties, ['order_id']);
122
+
123
+ const normalizedProps: OrderProperties = {
124
+ order_id: properties.order_id,
125
+ affiliation: properties.affiliation,
126
+ coupon: properties.coupon,
127
+ currency: validateCurrency(properties.currency),
128
+ discount: properties.discount,
129
+ products: properties.products ? normalizeProducts(properties.products) : undefined,
130
+ revenue: properties.revenue,
131
+ shipping: properties.shipping,
132
+ tax: properties.tax,
133
+ total: properties.total,
134
+ };
135
+
136
+ return {
137
+ name: ECOMMERCE_EVENTS.ORDER_CANCELLED,
138
+ category: 'ecommerce',
139
+ properties: cleanProperties(normalizedProps),
140
+ requiredProperties: ['order_id'],
141
+ };
142
+ }
143
+
144
+ /**
145
+ * Track order status changes (shipping, delivery, etc.)
146
+ */
147
+ export function orderStatusUpdated(properties: OrderStatusProperties): EcommerceEventSpec {
148
+ validateRequiredProperties(properties, ['order_id', 'status']);
149
+
150
+ return {
151
+ name: ECOMMERCE_EVENTS.ORDER_STATUS_UPDATED,
152
+ category: 'ecommerce',
153
+ properties: cleanProperties(properties),
154
+ requiredProperties: ['order_id', 'status'],
155
+ };
156
+ }
157
+
158
+ /**
159
+ * Track when a return is requested
160
+ */
161
+ export function returnRequested(properties: ReturnProperties): EcommerceEventSpec {
162
+ validateRequiredProperties(properties, ['order_id', 'reason']);
163
+
164
+ const normalizedProps = {
165
+ ...properties,
166
+ products: normalizeProducts(properties.products),
167
+ };
168
+
169
+ return {
170
+ name: ECOMMERCE_EVENTS.RETURN_REQUESTED,
171
+ category: 'ecommerce',
172
+ properties: cleanProperties(normalizedProps),
173
+ requiredProperties: ['order_id', 'reason'],
174
+ };
175
+ }
176
+
177
+ /**
178
+ * Track when a return is completed
179
+ */
180
+ export function returnCompleted(
181
+ properties: ReturnProperties & {
182
+ completion_date?: string;
183
+ refund_status?: 'pending' | 'completed' | 'failed';
184
+ },
185
+ ): EcommerceEventSpec {
186
+ validateRequiredProperties(properties, ['order_id', 'return_id']);
187
+
188
+ const normalizedProps = {
189
+ ...properties,
190
+ products: normalizeProducts(properties.products),
191
+ };
192
+
193
+ return {
194
+ name: ECOMMERCE_EVENTS.RETURN_COMPLETED,
195
+ category: 'ecommerce',
196
+ properties: cleanProperties(normalizedProps),
197
+ requiredProperties: ['order_id', 'return_id'],
198
+ };
199
+ }
@@ -0,0 +1,205 @@
1
+ /**
2
+ * @fileoverview Product-related ecommerce events
3
+ * Product-related ecommerce events
4
+ */
5
+
6
+ import { trackEcommerce } from '../track-ecommerce';
7
+ import {
8
+ type BaseProductProperties,
9
+ ECOMMERCE_EVENTS,
10
+ type EcommerceEventSpec,
11
+ type ProductComparisonProperties,
12
+ type ProductListProperties,
13
+ type RecommendationProperties,
14
+ type SearchResultsProperties,
15
+ } from '../types';
16
+ import {
17
+ cleanProperties,
18
+ normalizeProductProperties,
19
+ normalizeProducts,
20
+ validateRequiredProperties,
21
+ } from '../utils';
22
+
23
+ import type { EmitterOptions, EmitterTrackPayload } from '../../emitter-types';
24
+
25
+ /**
26
+ * Track when a user searches for products
27
+ */
28
+ export function productSearched(
29
+ properties: { query: string },
30
+ options?: EmitterOptions,
31
+ ): EmitterTrackPayload {
32
+ validateRequiredProperties(properties, ['query']);
33
+
34
+ const eventSpec: EcommerceEventSpec = {
35
+ name: ECOMMERCE_EVENTS.PRODUCT_SEARCHED,
36
+ category: 'ecommerce',
37
+ properties: cleanProperties(properties),
38
+ requiredProperties: ['query'],
39
+ };
40
+
41
+ return trackEcommerce(eventSpec, options);
42
+ }
43
+
44
+ /**
45
+ * Track when search results are displayed
46
+ */
47
+ export function searchResultsViewed(properties: SearchResultsProperties): EcommerceEventSpec {
48
+ validateRequiredProperties(properties, ['query', 'results_count']);
49
+
50
+ const normalizedProps = {
51
+ ...properties,
52
+ products: properties.products ? normalizeProducts(properties.products) : undefined,
53
+ };
54
+
55
+ return {
56
+ name: ECOMMERCE_EVENTS.SEARCH_RESULTS_VIEWED,
57
+ category: 'ecommerce',
58
+ properties: cleanProperties(normalizedProps),
59
+ requiredProperties: ['query', 'results_count'],
60
+ };
61
+ }
62
+
63
+ /**
64
+ * Track when a user views a product list or category
65
+ */
66
+ export function productListViewed(
67
+ properties: ProductListProperties,
68
+ ): EcommerceEventSpec<ProductListProperties> {
69
+ const normalizedProps: ProductListProperties = {
70
+ list_id: properties.list_id,
71
+ category: properties.category,
72
+ products: properties.products ? normalizeProducts(properties.products) : undefined,
73
+ };
74
+
75
+ return {
76
+ name: ECOMMERCE_EVENTS.PRODUCT_LIST_VIEWED,
77
+ category: 'ecommerce',
78
+ properties: cleanProperties(normalizedProps),
79
+ requiredProperties: [],
80
+ };
81
+ }
82
+
83
+ /**
84
+ * Track when a user filters a product list
85
+ */
86
+ export function productListFiltered(
87
+ properties: ProductListProperties & { filters?: Record<string, any> },
88
+ ): EcommerceEventSpec {
89
+ const normalizedProps = {
90
+ list_id: properties.list_id,
91
+ category: properties.category,
92
+ filters: properties.filters,
93
+ products: properties.products ? normalizeProducts(properties.products) : undefined,
94
+ };
95
+
96
+ return {
97
+ name: ECOMMERCE_EVENTS.PRODUCT_LIST_FILTERED,
98
+ category: 'ecommerce',
99
+ properties: cleanProperties(normalizedProps),
100
+ requiredProperties: [],
101
+ };
102
+ }
103
+
104
+ /**
105
+ * Track when a user clicks on a product
106
+ */
107
+ export function productClicked(properties: BaseProductProperties): EcommerceEventSpec {
108
+ const normalizedProps = normalizeProductProperties(properties);
109
+ validateRequiredProperties(normalizedProps, ['product_id']);
110
+
111
+ return {
112
+ name: ECOMMERCE_EVENTS.PRODUCT_CLICKED,
113
+ category: 'ecommerce',
114
+ properties: cleanProperties(normalizedProps),
115
+ requiredProperties: ['product_id'],
116
+ };
117
+ }
118
+
119
+ /**
120
+ * Track when a user views a product detail page
121
+ */
122
+ export function productViewed(
123
+ properties: BaseProductProperties,
124
+ options?: EmitterOptions,
125
+ ): EmitterTrackPayload {
126
+ const normalizedProps = normalizeProductProperties(properties);
127
+ validateRequiredProperties(normalizedProps, ['product_id']);
128
+
129
+ const eventSpec: EcommerceEventSpec = {
130
+ name: ECOMMERCE_EVENTS.PRODUCT_VIEWED,
131
+ category: 'ecommerce',
132
+ properties: cleanProperties(normalizedProps),
133
+ requiredProperties: ['product_id'],
134
+ };
135
+
136
+ return trackEcommerce(eventSpec, options);
137
+ }
138
+
139
+ /**
140
+ * Track when a user compares products
141
+ */
142
+ export function productCompared(properties: ProductComparisonProperties): EcommerceEventSpec {
143
+ const { action, comparison_list, product } = properties;
144
+ const normalizedProduct = normalizeProductProperties(product);
145
+ validateRequiredProperties(normalizedProduct, ['product_id']);
146
+
147
+ return {
148
+ name: ECOMMERCE_EVENTS.PRODUCT_COMPARED,
149
+ category: 'ecommerce',
150
+ properties: cleanProperties({
151
+ action,
152
+ ...normalizedProduct,
153
+ comparison_list: comparison_list ? normalizeProducts(comparison_list) : undefined,
154
+ }),
155
+ requiredProperties: ['product_id'],
156
+ };
157
+ }
158
+
159
+ /**
160
+ * Track when product recommendations are viewed
161
+ */
162
+ export function productRecommendationViewed(
163
+ properties: RecommendationProperties,
164
+ ): EcommerceEventSpec {
165
+ validateRequiredProperties(properties, ['recommendation_type', 'source']);
166
+
167
+ const normalizedProps = {
168
+ ...properties,
169
+ products: normalizeProducts(properties.products),
170
+ };
171
+
172
+ return {
173
+ name: ECOMMERCE_EVENTS.PRODUCT_RECOMMENDATION_VIEWED,
174
+ category: 'ecommerce',
175
+ properties: cleanProperties(normalizedProps),
176
+ requiredProperties: ['recommendation_type', 'source'],
177
+ };
178
+ }
179
+
180
+ /**
181
+ * Track when a recommended product is clicked
182
+ */
183
+ export function productRecommendationClicked(
184
+ properties: BaseProductProperties & {
185
+ recommendation_type: string;
186
+ source: string;
187
+ position?: number;
188
+ },
189
+ ): EcommerceEventSpec {
190
+ const { recommendation_type, position, source, ...productProps } = properties;
191
+ const normalizedProduct = normalizeProductProperties(productProps);
192
+ validateRequiredProperties(normalizedProduct, ['product_id']);
193
+
194
+ return {
195
+ name: ECOMMERCE_EVENTS.PRODUCT_RECOMMENDATION_CLICKED,
196
+ category: 'ecommerce',
197
+ properties: cleanProperties({
198
+ ...normalizedProduct,
199
+ recommendation_type,
200
+ position,
201
+ source,
202
+ }),
203
+ requiredProperties: ['product_id'],
204
+ };
205
+ }
@@ -0,0 +1,123 @@
1
+ /**
2
+ * @fileoverview Universal registry events for gift registries, wishlists, and similar features
3
+ * Universal registry events for gift registries, wishlists, and similar features
4
+ * Uses action-based patterns for efficient tracking
5
+ */
6
+
7
+ import {
8
+ ECOMMERCE_EVENTS,
9
+ type EcommerceEventSpec,
10
+ type RegistryItemProperties,
11
+ type RegistryProperties,
12
+ } from '../types';
13
+ import { cleanProperties, normalizeProductProperties, validateRequiredProperties } from '../utils';
14
+
15
+ /**
16
+ * Track registry management actions (create, update, delete)
17
+ */
18
+ export function registryManaged(
19
+ properties: RegistryProperties & {
20
+ action: 'created' | 'updated' | 'deleted';
21
+ updated_fields?: string[];
22
+ },
23
+ ): EcommerceEventSpec {
24
+ validateRequiredProperties(properties, ['registry_id', 'action']);
25
+
26
+ return {
27
+ name: ECOMMERCE_EVENTS.REGISTRY_MANAGED,
28
+ category: 'ecommerce',
29
+ properties: cleanProperties(properties),
30
+ requiredProperties: ['registry_id', 'action'],
31
+ };
32
+ }
33
+
34
+ /**
35
+ * Track when someone views a registry
36
+ */
37
+ export function registryViewed(
38
+ properties: RegistryProperties & {
39
+ viewer_id?: string;
40
+ viewer_relationship?: 'owner' | 'co_owner' | 'friend' | 'family' | 'other';
41
+ items_count?: number;
42
+ items_fulfilled?: number;
43
+ },
44
+ ): EcommerceEventSpec {
45
+ validateRequiredProperties(properties, ['registry_id']);
46
+
47
+ return {
48
+ name: ECOMMERCE_EVENTS.REGISTRY_VIEWED,
49
+ category: 'ecommerce',
50
+ properties: cleanProperties(properties),
51
+ requiredProperties: ['registry_id'],
52
+ };
53
+ }
54
+
55
+ /**
56
+ * Track when a registry is shared
57
+ */
58
+ export function registryShared(
59
+ properties: RegistryProperties & {
60
+ share_method: 'email' | 'social' | 'link' | 'qr_code' | 'other';
61
+ recipients_count?: number;
62
+ message?: string;
63
+ },
64
+ ): EcommerceEventSpec {
65
+ validateRequiredProperties(properties, ['registry_id', 'share_method']);
66
+
67
+ return {
68
+ name: ECOMMERCE_EVENTS.REGISTRY_SHARED,
69
+ category: 'ecommerce',
70
+ properties: cleanProperties(properties),
71
+ requiredProperties: ['registry_id', 'share_method'],
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Track registry item management (add, remove, update, purchase)
77
+ */
78
+ export function registryItemManaged(
79
+ properties: RegistryItemProperties & {
80
+ action: 'added' | 'removed' | 'updated' | 'purchased';
81
+ purchaser_id?: string;
82
+ purchaser_name?: string;
83
+ purchase_quantity?: number;
84
+ purchase_message?: string;
85
+ gift_wrap?: boolean;
86
+ anonymous_gift?: boolean;
87
+ updated_fields?: string[];
88
+ },
89
+ ): EcommerceEventSpec {
90
+ const {
91
+ purchaser_id,
92
+ registry_id,
93
+ purchaser_name,
94
+ action,
95
+ anonymous_gift,
96
+ gift_wrap,
97
+ purchase_message,
98
+ purchase_quantity,
99
+ updated_fields,
100
+ ...productProps
101
+ } = properties;
102
+
103
+ const normalizedProduct = normalizeProductProperties(productProps);
104
+ validateRequiredProperties(properties, ['registry_id', 'product_id', 'action']);
105
+
106
+ return {
107
+ name: ECOMMERCE_EVENTS.REGISTRY_ITEM_MANAGED,
108
+ category: 'ecommerce',
109
+ properties: cleanProperties({
110
+ purchaser_id,
111
+ registry_id,
112
+ purchaser_name,
113
+ action,
114
+ anonymous_gift,
115
+ gift_wrap,
116
+ purchase_message,
117
+ purchase_quantity,
118
+ updated_fields,
119
+ ...normalizedProduct,
120
+ }),
121
+ requiredProperties: ['registry_id', 'product_id', 'action'],
122
+ };
123
+ }