@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.
- package/README.md +509 -0
- package/dist/ai-YMnynb-t.mjs +3347 -0
- package/dist/ai-YMnynb-t.mjs.map +1 -0
- package/dist/chunk-DQk6qfdC.mjs +18 -0
- package/dist/client-CTzJVFU5.mjs +9 -0
- package/dist/client-CTzJVFU5.mjs.map +1 -0
- package/dist/client-CcFTauAh.mjs +54 -0
- package/dist/client-CcFTauAh.mjs.map +1 -0
- package/dist/client-CeOLjbac.mjs +281 -0
- package/dist/client-CeOLjbac.mjs.map +1 -0
- package/dist/client-D339NFJS.mjs +267 -0
- package/dist/client-D339NFJS.mjs.map +1 -0
- package/dist/client-next.d.mts +62 -0
- package/dist/client-next.d.mts.map +1 -0
- package/dist/client-next.mjs +525 -0
- package/dist/client-next.mjs.map +1 -0
- package/dist/client.d.mts +30 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +186 -0
- package/dist/client.mjs.map +1 -0
- package/dist/config-DPS6bSYo.d.mts +34 -0
- package/dist/config-DPS6bSYo.d.mts.map +1 -0
- package/dist/config-P6P5adJg.mjs +287 -0
- package/dist/config-P6P5adJg.mjs.map +1 -0
- package/dist/console-8bND3mMU.mjs +128 -0
- package/dist/console-8bND3mMU.mjs.map +1 -0
- package/dist/ecommerce-Cgu4wlux.mjs +993 -0
- package/dist/ecommerce-Cgu4wlux.mjs.map +1 -0
- package/dist/emitters-6-nKo8i-.mjs +208 -0
- package/dist/emitters-6-nKo8i-.mjs.map +1 -0
- package/dist/emitters-DldkVSPp.d.mts +12 -0
- package/dist/emitters-DldkVSPp.d.mts.map +1 -0
- package/dist/index-BfNWgfa5.d.mts +1494 -0
- package/dist/index-BfNWgfa5.d.mts.map +1 -0
- package/dist/index-BkIWe--N.d.mts +953 -0
- package/dist/index-BkIWe--N.d.mts.map +1 -0
- package/dist/index-jPzXRn52.d.mts +184 -0
- package/dist/index-jPzXRn52.d.mts.map +1 -0
- package/dist/manager-DvRRjza6.d.mts +76 -0
- package/dist/manager-DvRRjza6.d.mts.map +1 -0
- package/dist/posthog-bootstrap-CYfIy_WS.mjs +1769 -0
- package/dist/posthog-bootstrap-CYfIy_WS.mjs.map +1 -0
- package/dist/posthog-bootstrap-DWxFrxlt.d.mts +81 -0
- package/dist/posthog-bootstrap-DWxFrxlt.d.mts.map +1 -0
- package/dist/providers-http-client.d.mts +37 -0
- package/dist/providers-http-client.d.mts.map +1 -0
- package/dist/providers-http-client.mjs +320 -0
- package/dist/providers-http-client.mjs.map +1 -0
- package/dist/providers-http-server.d.mts +31 -0
- package/dist/providers-http-server.d.mts.map +1 -0
- package/dist/providers-http-server.mjs +297 -0
- package/dist/providers-http-server.mjs.map +1 -0
- package/dist/providers-http.d.mts +46 -0
- package/dist/providers-http.d.mts.map +1 -0
- package/dist/providers-http.mjs +4 -0
- package/dist/server-edge.d.mts +9 -0
- package/dist/server-edge.d.mts.map +1 -0
- package/dist/server-edge.mjs +373 -0
- package/dist/server-edge.mjs.map +1 -0
- package/dist/server-next.d.mts +67 -0
- package/dist/server-next.d.mts.map +1 -0
- package/dist/server-next.mjs +193 -0
- package/dist/server-next.mjs.map +1 -0
- package/dist/server.d.mts +10 -0
- package/dist/server.mjs +7 -0
- package/dist/service-cYtBBL8x.mjs +945 -0
- package/dist/service-cYtBBL8x.mjs.map +1 -0
- package/dist/shared.d.mts +16 -0
- package/dist/shared.d.mts.map +1 -0
- package/dist/shared.mjs +93 -0
- package/dist/shared.mjs.map +1 -0
- package/dist/types-BxBnNQ0V.d.mts +354 -0
- package/dist/types-BxBnNQ0V.d.mts.map +1 -0
- package/dist/types-CBvxUEaF.d.mts +216 -0
- package/dist/types-CBvxUEaF.d.mts.map +1 -0
- package/dist/types.d.mts +4 -0
- package/dist/types.mjs +0 -0
- package/dist/vercel-types-lwakUfoI.d.mts +102 -0
- package/dist/vercel-types-lwakUfoI.d.mts.map +1 -0
- package/package.json +129 -0
- package/src/client/index.ts +164 -0
- package/src/client/manager.ts +71 -0
- package/src/client/next/components.tsx +270 -0
- package/src/client/next/hooks.ts +217 -0
- package/src/client/next/manager.ts +141 -0
- package/src/client/next.ts +144 -0
- package/src/client-next.ts +101 -0
- package/src/client.ts +89 -0
- package/src/examples/ai-sdk-patterns.ts +583 -0
- package/src/examples/emitter-patterns.ts +476 -0
- package/src/examples/nextjs-emitter-patterns.tsx +403 -0
- package/src/next/app-router.tsx +564 -0
- package/src/next/client.ts +419 -0
- package/src/next/index.ts +84 -0
- package/src/next/middleware.ts +429 -0
- package/src/next/rsc.tsx +300 -0
- package/src/next/server.ts +253 -0
- package/src/next/types.d.ts +220 -0
- package/src/providers/base-provider.ts +419 -0
- package/src/providers/console/client.ts +10 -0
- package/src/providers/console/index.ts +152 -0
- package/src/providers/console/server.ts +6 -0
- package/src/providers/console/types.ts +15 -0
- package/src/providers/http/client.ts +464 -0
- package/src/providers/http/index.ts +30 -0
- package/src/providers/http/server.ts +396 -0
- package/src/providers/http/types.ts +135 -0
- package/src/providers/posthog/client.ts +518 -0
- package/src/providers/posthog/index.ts +11 -0
- package/src/providers/posthog/server.ts +329 -0
- package/src/providers/posthog/types.ts +104 -0
- package/src/providers/segment/client.ts +113 -0
- package/src/providers/segment/index.ts +11 -0
- package/src/providers/segment/server.ts +115 -0
- package/src/providers/segment/types.ts +51 -0
- package/src/providers/vercel/client.ts +102 -0
- package/src/providers/vercel/index.ts +11 -0
- package/src/providers/vercel/server.ts +89 -0
- package/src/providers/vercel/types.ts +27 -0
- package/src/server/index.ts +103 -0
- package/src/server/manager.ts +62 -0
- package/src/server/next.ts +210 -0
- package/src/server-edge.ts +442 -0
- package/src/server-next.ts +39 -0
- package/src/server.ts +106 -0
- package/src/shared/emitters/ai/README.md +981 -0
- package/src/shared/emitters/ai/events/agent.ts +130 -0
- package/src/shared/emitters/ai/events/artifacts.ts +167 -0
- package/src/shared/emitters/ai/events/chat.ts +126 -0
- package/src/shared/emitters/ai/events/chatbot-ecommerce.ts +133 -0
- package/src/shared/emitters/ai/events/completion.ts +103 -0
- package/src/shared/emitters/ai/events/content-generation.ts +347 -0
- package/src/shared/emitters/ai/events/conversation.ts +332 -0
- package/src/shared/emitters/ai/events/product-features.ts +1402 -0
- package/src/shared/emitters/ai/events/streaming.ts +114 -0
- package/src/shared/emitters/ai/events/tool.ts +93 -0
- package/src/shared/emitters/ai/index.ts +69 -0
- package/src/shared/emitters/ai/track-ai-sdk.ts +74 -0
- package/src/shared/emitters/ai/track-ai.ts +50 -0
- package/src/shared/emitters/ai/types.ts +1041 -0
- package/src/shared/emitters/ai/utils.ts +468 -0
- package/src/shared/emitters/ecommerce/events/cart-checkout.ts +106 -0
- package/src/shared/emitters/ecommerce/events/coupon.ts +49 -0
- package/src/shared/emitters/ecommerce/events/engagement.ts +61 -0
- package/src/shared/emitters/ecommerce/events/marketplace.ts +119 -0
- package/src/shared/emitters/ecommerce/events/order.ts +199 -0
- package/src/shared/emitters/ecommerce/events/product.ts +205 -0
- package/src/shared/emitters/ecommerce/events/registry.ts +123 -0
- package/src/shared/emitters/ecommerce/events/wishlist-sharing.ts +140 -0
- package/src/shared/emitters/ecommerce/index.ts +46 -0
- package/src/shared/emitters/ecommerce/track-ecommerce.ts +53 -0
- package/src/shared/emitters/ecommerce/types.ts +314 -0
- package/src/shared/emitters/ecommerce/utils.ts +216 -0
- package/src/shared/emitters/emitter-types.ts +974 -0
- package/src/shared/emitters/emitters.ts +292 -0
- package/src/shared/emitters/helpers.ts +419 -0
- package/src/shared/emitters/index.ts +66 -0
- package/src/shared/index.ts +142 -0
- package/src/shared/ingestion/index.ts +66 -0
- package/src/shared/ingestion/schemas.ts +386 -0
- package/src/shared/ingestion/service.ts +628 -0
- package/src/shared/node22-features.ts +848 -0
- package/src/shared/providers/console-provider.ts +160 -0
- package/src/shared/types/base-types.ts +54 -0
- package/src/shared/types/console-types.ts +19 -0
- package/src/shared/types/posthog-types.ts +131 -0
- package/src/shared/types/segment-types.ts +15 -0
- package/src/shared/types/types.ts +397 -0
- package/src/shared/types/vercel-types.ts +19 -0
- package/src/shared/utils/config-client.ts +19 -0
- package/src/shared/utils/config.ts +250 -0
- package/src/shared/utils/emitter-adapter.ts +212 -0
- package/src/shared/utils/manager.test.ts +36 -0
- package/src/shared/utils/manager.ts +1322 -0
- package/src/shared/utils/posthog-bootstrap.ts +136 -0
- package/src/shared/utils/posthog-client-utils.ts +48 -0
- package/src/shared/utils/posthog-next-utils.ts +282 -0
- package/src/shared/utils/posthog-server-utils.ts +210 -0
- package/src/shared/utils/rate-limit.ts +289 -0
- package/src/shared/utils/security.ts +545 -0
- package/src/shared/utils/validation-client.ts +161 -0
- package/src/shared/utils/validation.ts +399 -0
- package/src/shared.ts +155 -0
- 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
|
+
}
|